Effective C++ changes
[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),
67   fStringLayout(new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 5, 2, 2)),
68   fStringLabel(new TGLabel(fFrame, label)),
69   fStringEntry(new TGTextEntry(fFrame, string.Data())),
70   fString(string)
71 {
72 // create a dialog for connecting to a monitor process
73
74   fFrame->AddFrame(fStringLabel, fStringLayout);
75   fStringEntry->Resize(100, fStringEntry->GetDefaultHeight());
76   fFrame->AddFrame(fStringEntry, fStringLayout);
77
78   fString = "";
79
80   fMain->SetWindowName(title);
81   fMain->MapSubwindows();
82   fMain->Layout();
83   gClient->WaitFor(fMain);
84 }
85
86 //_____________________________________________________________________________
87 AliMonitorClient::AliMonitorStringDlg::~AliMonitorStringDlg()
88 {
89 // clean up
90
91   delete fStringLabel;
92   delete fStringLayout;
93   delete fStringEntry;
94 }
95
96 //_____________________________________________________________________________
97 void AliMonitorClient::AliMonitorStringDlg::OnOkClicked()
98 {
99   fString = fStringEntry->GetText();
100 }
101
102
103 //_____________________________________________________________________________
104 AliMonitorClient::AliMonitorNumberDlg::AliMonitorNumberDlg(Float_t& value, 
105                                                            TGFrame* main, 
106                                                            const char* title, 
107                                                            const char* label, 
108                                                            Float_t min) :
109   AliMonitorDialog(main, 250, 80),
110   fNumberLayout(new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 5, 2, 2)),
111   fNumberLabel(new TGLabel(fFrame, label)),
112   fNumberEntry(new TGNumberEntry(fFrame, value, 4, -1, TGNumberFormat::kNESRealOne)),
113   fNumber(value)
114 {
115 // create a dialog for getting a number
116
117   fFrame->AddFrame(fNumberLabel, fNumberLayout);
118   fNumberEntry->SetLimits(TGNumberFormat::kNELLimitMin, min, 0);
119   fFrame->AddFrame(fNumberEntry, fNumberLayout);
120
121   fNumber = -1;
122
123   fMain->SetWindowName(title);
124   fMain->MapSubwindows();
125   fMain->Layout();
126   gClient->WaitFor(fMain);
127 }
128
129 //_____________________________________________________________________________
130 AliMonitorClient::AliMonitorNumberDlg::~AliMonitorNumberDlg()
131 {
132 // clean up
133
134   delete fNumberLabel;
135   delete fNumberLayout;
136   delete fNumberEntry;
137 }
138
139 //_____________________________________________________________________________
140 void AliMonitorClient::AliMonitorNumberDlg::OnOkClicked()
141 {
142   fNumber = fNumberEntry->GetNumber();
143 }
144
145
146
147 // constants for menu entries
148 enum {kMenuFileConnect, kMenuFileDisconnect, kMenuFileOpen, kMenuFileExit,
149       kMenuViewToolBar, kMenuViewTree, kMenuViewDescription, 
150       kMenuViewReference, kMenuViewStatistics,
151       kMenuFavAdd, kMenuFavDelete, 
152       kMenuFavLoad, kMenuFavSave,  kMenuFavSaveAs, kMenuFavSaveOnExit,
153       kMenuRefLoad, kMenuRefThreshold, 
154       kMenuRefTakeCurrent, kMenuRefSave, kMenuRefSaveAs,
155       kMenuOptLoop, kMenuOptPrint, 
156       kMenuOptSave, kMenuOptSaveOnExit,
157       kMenuHelpDoc, kMenuHelpAbout
158 };
159
160 //_____________________________________________________________________________
161 AliMonitorClient::AliMonitorClient():
162   TGMainFrame(gClient->GetRoot(), 500, 300),
163   fQObject(),
164   fMenuBarLayout(new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 0, 0, 1, 1)),
165   fMenuBarItemLayout(new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0)),
166   fMenuBarHelpLayout(new TGLayoutHints(kLHintsTop | kLHintsRight)),
167   fMenuFile(new TGPopupMenu(gClient->GetRoot())),
168   fMenuView(new TGPopupMenu(gClient->GetRoot())),
169   fMenuFavorites(new TGPopupMenu(gClient->GetRoot())),
170   fMenuReference(new TGPopupMenu(gClient->GetRoot())),
171   fMenuOptions(new TGPopupMenu(gClient->GetRoot())),
172   fMenuHelp(new TGPopupMenu(gClient->GetRoot())),
173   fMenuBar(new TGMenuBar(this, 1, 1, kHorizontalFrame)),
174   fToolBarLayout(new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 2, 2)),
175   fToolBarSep(new TGHorizontal3DLine(this)),
176   fToolBar(new TGToolBar(this, 60, 20, kHorizontalFrame)),
177   fEventNumberLayout(new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 10, 2, 10, 5)),
178   fEventNumber(new TGNumberEntry(fToolBar, 1, 4, 10, TGNumberFormat::kNESInteger)),
179   fEventButton(NULL),
180   fSumButton(NULL),
181   fRunButton(NULL),
182   fLoopButton(NULL),
183   fLoopOnPicture(NULL),
184   fLoopOffPicture(NULL),
185   fPreviousButton(NULL),
186   fNextButton(NULL),
187   fCopyButton(NULL),
188   fSaveButton(NULL),
189   fPrintButton(NULL),
190   fBottomLayout(new TGLayoutHints(kLHintsExpandX | kLHintsBottom)),
191   fLeftLayout(new TGLayoutHints(kLHintsLeft | kLHintsExpandY)),
192   fExpandLayout(new TGLayoutHints(kLHintsExpandX | kLHintsExpandY)),
193   fVerticalFrame(new TGVerticalFrame(this, 10, 10)),
194   fHorizontalFrame(new TGHorizontalFrame(fVerticalFrame, 10, 10)),
195   fTreeFrame(new TGCompositeFrame(fHorizontalFrame, 10, 10, kSunkenFrame | kFixedWidth)),
196   fTreeCanvas(new TGCanvas(fTreeFrame, 10, 10)),
197   fTree(new TGListTree(fTreeCanvas, kHorizontalFrame)),
198   fHistoPicture(fClient->GetPicture("h1_t.xpm")),
199   fAllItem(fTree->AddItem(NULL, "All")),
200   fFavoritesItem(fTree->AddItem(NULL, "Favorites")),
201   fComparisonItem(fTree->AddItem(NULL, "Comparison")),
202   fTreeSplitter(new TGVSplitter(fHorizontalFrame, 4)),
203   fDrawFrame(new TGCompositeFrame(fHorizontalFrame, 10, 10, kSunkenFrame)),
204   fDrawCanvas(new TRootEmbeddedCanvas("current monitor histogram", fDrawFrame, 10, 10)),
205   fDescriptionSplitter(new TGHSplitter(fVerticalFrame, 4, 4)),
206   fDescriptionFrame(new TGCompositeFrame(fVerticalFrame, 10, 60, kSunkenFrame | kFixedHeight)),
207   fDescription(new TGTextView(fDescriptionFrame, 10, 60, "")),
208   fServerName("localhost"),
209   fSocket(NULL),
210   fSocketHandler(NULL),
211   fFolder(CreateTopFolder()),
212   fCurrentItem(NULL),
213   fBaseItem(NULL),
214   fLoopTimer(NULL),
215   fLoopInterval(1000),
216   fFavoritesFileName(""),
217   fReferenceFileName(""),
218   fReference(CreateTopFolder()),
219   fPrintCommand("gv")
220 {
221 // initialize the monitoring client window
222
223   // File menu
224   fMenuFile->AddEntry("&Connect...", kMenuFileConnect);
225   fMenuFile->AddEntry("&Disconnect...", kMenuFileDisconnect);
226   fMenuFile->HideEntry(kMenuFileDisconnect);
227   fMenuFile->AddEntry("&Open...", kMenuFileOpen);
228   fMenuFile->AddSeparator();
229   fMenuFile->AddEntry("E&xit", kMenuFileExit);
230   fMenuFile->Connect("Activated(Int_t)", "AliMonitorClient", this,
231                      "OnMenuActivated(Int_t)");
232
233   // View menu
234   fMenuView->AddEntry("Tool&bar", kMenuViewToolBar);
235   fMenuView->CheckEntry(kMenuViewToolBar);
236   fMenuView->AddEntry("&Tree", kMenuViewTree);
237   fMenuView->CheckEntry(kMenuViewTree);
238   fMenuView->AddEntry("&Description", kMenuViewDescription);
239   fMenuView->CheckEntry(kMenuViewDescription);
240   fMenuView->AddSeparator();
241   fMenuView->AddEntry("&Reference", kMenuViewReference);
242   fMenuView->CheckEntry(kMenuViewReference);
243   AliMonitorHisto::SetDrawRef(kTRUE);
244   fMenuView->AddEntry("&Statistics", kMenuViewStatistics);
245   fMenuView->CheckEntry(kMenuViewStatistics);
246   gStyle->SetOptStat(1110);
247   fMenuView->Connect("Activated(Int_t)", "AliMonitorClient", this,
248                      "OnMenuActivated(Int_t)");
249
250   // Favorites menu
251   fMenuFavorites->AddEntry("&Add", kMenuFavAdd);
252   fMenuFavorites->DisableEntry(kMenuFavAdd);
253   fMenuFavorites->AddEntry("&Delete", kMenuFavDelete);
254   fMenuFavorites->DisableEntry(kMenuFavDelete);
255   fMenuFavorites->AddSeparator();
256   fMenuFavorites->AddEntry("&Load...", kMenuFavLoad);
257   fMenuFavorites->AddEntry("&Save", kMenuFavSave);
258   fMenuFavorites->DisableEntry(kMenuFavSave);
259   fMenuFavorites->AddEntry("&Save As...", kMenuFavSaveAs);
260   fMenuFavorites->DisableEntry(kMenuFavSaveAs);
261   fMenuFavorites->AddEntry("Save On &Exit", kMenuFavSaveOnExit);
262   fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
263   fMenuFavorites->Connect("Activated(Int_t)", "AliMonitorClient", this,
264                           "OnMenuActivated(Int_t)");
265
266   // Reference menu
267   fMenuReference->AddEntry("&Load...", kMenuRefLoad);
268   fMenuReference->AddEntry("&Threshold...", kMenuRefThreshold);
269   fMenuReference->AddSeparator();
270   fMenuReference->AddEntry("Take &Current", kMenuRefTakeCurrent);
271   fMenuReference->DisableEntry(kMenuRefTakeCurrent);
272   fMenuReference->AddEntry("&Save", kMenuRefSave);
273   fMenuReference->DisableEntry(kMenuRefSave);
274   fMenuReference->AddEntry("Save &As...", kMenuRefSaveAs);
275   fMenuReference->DisableEntry(kMenuRefSaveAs);
276   fMenuReference->Connect("Activated(Int_t)", "AliMonitorClient", this,
277                           "OnMenuActivated(Int_t)");
278
279   // Options menu
280   fMenuOptions->AddEntry("&Loop Interval...", kMenuOptLoop);
281   fMenuOptions->AddEntry("&Print Command...", kMenuOptPrint);
282   fMenuOptions->AddSeparator();
283   fMenuOptions->AddEntry("&Save Settings", kMenuOptSave);
284   fMenuOptions->AddEntry("Save Settings on &Exit", kMenuOptSaveOnExit);
285   fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
286   fMenuOptions->Connect("Activated(Int_t)", "AliMonitorClient", this,
287                         "OnMenuActivated(Int_t)");
288
289   // Help menu
290   fMenuHelp->AddEntry("&Documentation...", kMenuHelpDoc);
291   fMenuHelp->AddEntry("A&bout...", kMenuHelpAbout);
292   fMenuHelp->Connect("Activated(Int_t)", "AliMonitorClient", this,
293                      "OnMenuActivated(Int_t)");
294
295   // menu bar
296   fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout);
297   fMenuBar->AddPopup("&View", fMenuView, fMenuBarItemLayout);
298   fMenuBar->AddPopup("F&avorites", fMenuFavorites, fMenuBarItemLayout);
299   fMenuBar->AddPopup("&Reference", fMenuReference, fMenuBarItemLayout);
300   fMenuBar->AddPopup("&Options", fMenuOptions, fMenuBarItemLayout);
301   fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout);
302
303   AddFrame(fMenuBar, fMenuBarLayout);
304
305
306   // *** tool bar ***
307   AddFrame(fToolBarSep, fToolBarLayout);
308   AddFrame(fToolBar, fToolBarLayout);
309
310   // event number field
311   fEventNumber->SetLimits(TGNumberFormat::kNELLimitMin, 1, 0);
312   fToolBar->AddFrame(fEventNumber, fEventNumberLayout);
313   fEventNumber->GetNumberEntry()->Connect("ReturnPressed()", 
314                                           "AliMonitorClient", this,
315                                           "OnEventNumberChanged()");
316   fEventNumber->GetButtonUp()->Connect("Clicked()", 
317                                        "AliMonitorClient", this,
318                                        "OnEventNumberChanged()");
319   fEventNumber->GetButtonDown()->Connect("Clicked()", 
320                                          "AliMonitorClient", this,
321                                          "OnEventNumberChanged()");
322
323   // draw event button
324   ToolBarData_t eventButton = {"h1_s.xpm", "draw event histogram", 
325                                kTRUE, 11, NULL};
326   fToolBar->AddButton(this, &eventButton, 5);
327   fEventButton = eventButton.fButton;
328   fEventButton->Connect("Pressed()", "AliMonitorClient", this,
329                         "OnEventButtonPressed()");
330
331   // draw sum button
332   ToolBarData_t sumButton = {"h2_s.xpm", "draw sum histogram", 
333                              kTRUE, 12, NULL};
334   fToolBar->AddButton(this, &sumButton, 5);
335   fSumButton = sumButton.fButton;
336   fSumButton->Connect("Pressed()", "AliMonitorClient", this,
337                       "OnSumButtonPressed()");
338
339   // draw run button
340   ToolBarData_t runButton = {"h3_s.xpm", "draw run histogram", 
341                              kTRUE, 13, NULL};
342   fToolBar->AddButton(this, &runButton, 5);
343   fRunButton = runButton.fButton;
344   fRunButton->SetDown(kTRUE);
345   fRunButton->Connect("Pressed()", "AliMonitorClient", this,
346                       "OnRunButtonPressed()");
347
348   // loop button
349   char fileName[256];
350   sprintf(fileName, "%s/MONITOR/loop_on.xpm", gSystem->Getenv("ALICE_ROOT"));
351   ToolBarData_t loopButton = {fileName, "loop over histograms", 
352                               kFALSE, 21, NULL};
353   fToolBar->AddButton(this, &loopButton, 25);
354   fLoopButton = loopButton.fButton;
355   fLoopButton->Connect("Clicked()", "AliMonitorClient", this,
356                        "OnLoopButtonClicked()");
357   fLoopOnPicture = gClient->GetPicture(fileName);
358   sprintf(fileName, "%s/MONITOR/loop_off2.xpm", gSystem->Getenv("ALICE_ROOT"));
359   fLoopOffPicture = gClient->GetPicture(fileName);
360
361   // previous button
362   sprintf(fileName, "%s/MONITOR/previous_s.xpm", 
363           gSystem->Getenv("ALICE_ROOT"));
364   ToolBarData_t previousButton = {fileName, "go to previous histogram", 
365                                   kFALSE, 22, NULL};
366   fToolBar->AddButton(this, &previousButton, 5);
367   fPreviousButton = previousButton.fButton;
368   fPreviousButton->Connect("Clicked()", "AliMonitorClient", this,
369                            "OnPreviousButtonClicked()");
370
371   // next button
372   sprintf(fileName, "%s/MONITOR/next_s.xpm", gSystem->Getenv("ALICE_ROOT"));
373   ToolBarData_t nextButton = {fileName, "go to next histogram", 
374                               kFALSE, 23, NULL};
375   fToolBar->AddButton(this, &nextButton, 5);
376   fNextButton = nextButton.fButton;
377   fNextButton->Connect("Clicked()", "AliMonitorClient", this,
378                        "OnNextButtonClicked()");
379
380   // copy button
381   sprintf(fileName, "%s/MONITOR/copy_s.xpm", gSystem->Getenv("ALICE_ROOT"));
382   ToolBarData_t copyButton = {fileName, 
383                               "copy the current histogram to a new canvas", 
384                               kFALSE, 31, NULL};
385   fToolBar->AddButton(this, &copyButton, 25);
386   fCopyButton = copyButton.fButton;
387   fCopyButton->Connect("Clicked()", "AliMonitorClient", this,
388                        "OnCopyButtonClicked()");
389
390   // save button
391   sprintf(fileName, "%s/MONITOR/save_s.xpm", gSystem->Getenv("ALICE_ROOT"));
392   ToolBarData_t saveButton = {fileName, "save the current histogram", 
393                               kFALSE, 32, NULL};
394   fToolBar->AddButton(this, &saveButton, 5);
395   fSaveButton = saveButton.fButton;
396   fSaveButton->Connect("Clicked()", "AliMonitorClient", this,
397                        "OnSaveButtonClicked()");
398
399   // print button
400   ToolBarData_t printButton = {"printer_s.xpm", "print the current histogram", 
401                              kFALSE, 33, NULL};
402   fToolBar->AddButton(this, &printButton, 5);
403   fPrintButton = printButton.fButton;
404   fPrintButton->Connect("Clicked()", "AliMonitorClient", this,
405                         "OnPrintButtonClicked()");
406
407   // *** frames ***
408   AddFrame(fVerticalFrame, fExpandLayout);
409
410   fVerticalFrame->AddFrame(fHorizontalFrame, fExpandLayout);
411
412   // tree frame
413   fHorizontalFrame->AddFrame(fTreeFrame, fLeftLayout);
414   fTreeFrame->AddFrame(fTreeCanvas, fExpandLayout);
415   fTreeCanvas->AddFrame(fTree, fExpandLayout);
416   fTree->Connect("Clicked(TGListTreeItem*,Int_t)", "AliMonitorClient",
417                  this, "OnTreeClicked(TGListTreeItem*,Int_t)");
418   fTree->Connect("ReturnPressed(TGListTreeItem*)", "AliMonitorClient",
419                  this, "OnTreeReturnPressed(TGListTreeItem*)");
420
421   // tree items
422   fTreeFrame->Resize(100, fTreeFrame->GetDefaultHeight());
423
424   // tree / histogram splitter
425   fTreeSplitter->SetFrame(fTreeFrame, kTRUE);
426   fHorizontalFrame->AddFrame(fTreeSplitter, fLeftLayout);
427
428   // histogram frame
429   fHorizontalFrame->AddFrame(fDrawFrame, fExpandLayout);
430   fDrawFrame->AddFrame(fDrawCanvas, fExpandLayout);
431
432   // description frame
433   fVerticalFrame->AddFrame(fDescriptionFrame, fBottomLayout);
434   fDescriptionFrame->AddFrame(fDescription, fExpandLayout);
435
436   // histogram / description splitter
437   fVerticalFrame->AddFrame(fDescriptionSplitter, fBottomLayout);
438   fDescriptionSplitter->SetFrame(fDescriptionFrame, kFALSE);
439
440   // main window
441   Connect("CloseWindow()", "AliMonitorClient", this, "CloseWindow()");
442   SetWindowName("Monitor Client");
443   SetWMSize(GetWidth(), GetHeight());
444   Move(100, 100);
445   SetWMPosition(100, 100);
446   MapSubwindows();
447   Layout();
448   MapWindow();
449
450
451   // default data members
452
453   fFolder = CreateTopFolder();
454
455   fReference = CreateTopFolder();
456   AliMonitorHisto::SetThreshold(5.0);
457
458   // load saved settings
459   LoadSettings();
460 }
461
462 //_____________________________________________________________________________
463 AliMonitorClient::~AliMonitorClient()
464 {
465 // clean up
466
467   delete fMenuBarLayout;
468   delete fMenuBarItemLayout;
469   delete fMenuBarHelpLayout;
470   delete fMenuFile;
471   delete fMenuView;
472   delete fMenuFavorites;
473   delete fMenuReference;
474   delete fMenuOptions;
475   delete fMenuHelp;
476   delete fMenuBar;
477
478   delete fEventNumberLayout;
479   delete fEventNumber;
480   delete fToolBarLayout;
481   delete fToolBarSep;
482   delete fToolBar;
483
484   delete fBottomLayout;
485   delete fLeftLayout;
486   delete fExpandLayout;
487
488   delete fTree;
489   delete fTreeCanvas;
490   delete fTreeFrame;
491   delete fTreeSplitter;
492
493   delete fDrawCanvas;
494   delete fDrawFrame;
495
496   delete fDescriptionSplitter;
497   delete fDescription;
498   delete fDescriptionFrame;
499
500   delete fVerticalFrame;
501   delete fHorizontalFrame;
502
503   if (fSocket) {
504     fSocketHandler->Remove();
505     fSocket->Send("disconnect");
506     fSocket->Close();
507     delete fSocket;
508     delete fSocketHandler;
509   }
510
511   if (fFolder) delete fFolder;
512
513   if (fLoopTimer) {
514     fLoopTimer->TurnOff();
515     delete fLoopTimer;
516   }
517
518   if (fReference) delete fReference;
519 }
520
521
522 //_____________________________________________________________________________
523 void AliMonitorClient::CloseWindow()
524 {
525 // terminate the application when the window is closed
526
527   if (fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit)) {
528     SaveFavorites();
529   }
530   if (fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit)) {
531     SaveSettings();
532   }
533   if (fSocket) {
534     fSocketHandler->Remove();
535     fSocket->Send("disconnect");
536     fSocket->Close();
537     delete fSocket;
538     fSocket = NULL;
539     delete fSocketHandler;
540     fSocketHandler = NULL;
541   }
542
543   gApplication->Terminate(0);
544 }
545
546
547 //_____________________________________________________________________________
548 void AliMonitorClient::OnNewData()
549 {
550 // called when data has arrived from the monitor server
551
552   if (CheckForNewData()) UpdateAll();
553 }
554
555
556 //_____________________________________________________________________________
557 void AliMonitorClient::OnMenuActivated(Int_t id)
558 {
559 // called when a menu item was selected
560
561   switch (id) {
562
563   case kMenuFileConnect: {
564     if (ConnectToServer()) UpdateAll();
565     break;
566   }
567
568   case kMenuFileDisconnect: {
569     DisconnectFromServer();
570     break;
571   }
572
573   case kMenuFileOpen: {
574     if (OpenFile()) UpdateAll();
575     break;
576   }
577
578   case kMenuFileExit: {
579     CloseWindow();
580     break;
581   }
582
583   case kMenuViewToolBar: {
584     ViewToolBar(!fMenuView->IsEntryChecked(kMenuViewToolBar));
585     break;
586   }
587
588   case kMenuViewTree: {
589     ViewTree(!fMenuView->IsEntryChecked(kMenuViewTree));
590     break;
591   }
592
593   case kMenuViewDescription: {
594     ViewDescription(!fMenuView->IsEntryChecked(kMenuViewDescription));
595     break;
596   }
597
598   case kMenuViewReference: {
599     ViewReference(!fMenuView->IsEntryChecked(kMenuViewReference));
600     UpdateHisto();
601     break;
602   }
603
604   case kMenuViewStatistics: {
605     ViewStatistics(!fMenuView->IsEntryChecked(kMenuViewStatistics));
606     UpdateHisto();
607     break;
608   }
609
610   case kMenuFavAdd: {
611     if (AddFavorite()) {
612       fMenuFavorites->EnableEntry(kMenuFavSave);
613       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
614     }
615     break;
616   }
617
618   case kMenuFavDelete: {
619     if (DeleteFavorite()) {
620       UpdateHisto();
621       UpdateDescription();
622       fMenuFavorites->DisableEntry(kMenuFavDelete);
623       fMenuFavorites->EnableEntry(kMenuFavSave);
624       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
625     }
626     break;
627   }
628
629   case kMenuFavLoad: {
630     if (LoadFavorites()) {
631       UpdateHisto();
632       UpdateDescription();
633       fMenuFavorites->DisableEntry(kMenuFavSave);
634       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
635     }
636     break;
637   }
638
639   case kMenuFavSave: {
640     if (SaveFavorites()) {
641       fMenuFavorites->DisableEntry(kMenuFavSave);
642     }
643     break;
644   }
645
646   case kMenuFavSaveAs: {
647     if (SaveFavoritesAs()) {
648       fMenuFavorites->DisableEntry(kMenuFavSave);
649     }
650     break;
651   }
652
653   case kMenuFavSaveOnExit: {
654     if (fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit)) {
655       fMenuFavorites->UnCheckEntry(kMenuFavSaveOnExit);
656     } else {
657       fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
658     }
659     break;
660   }
661
662   case kMenuRefLoad: {
663     if (LoadReference()) {
664       SetReference();
665       UpdateHisto();
666       UpdateComparisonTree();
667       fMenuReference->EnableEntry(kMenuRefSaveAs);
668     }
669     break;
670   }
671
672   case kMenuRefThreshold: {
673     Float_t threshold = AliMonitorHisto::GetThreshold();
674     new AliMonitorNumberDlg(threshold, this, 
675                             "Comparison with Reference Histograms",
676                             "threshold for comparison:", 0.);
677     if (threshold < 0) break;
678
679     AliMonitorHisto::SetThreshold(threshold);
680     UpdateHisto();
681     UpdateComparisonTree();
682     break;
683   }
684
685   case kMenuRefTakeCurrent: {
686     if (TakeCurrentReference()) {
687       UpdateHisto();
688       UpdateComparisonTree();
689       fMenuReference->EnableEntry(kMenuRefSave);
690       fMenuReference->EnableEntry(kMenuRefSaveAs);
691     }
692     break;
693   }
694
695   case kMenuRefSave: {
696     if (SaveReference()) {
697       fMenuReference->DisableEntry(kMenuRefSave);
698     }
699     break;
700   }
701
702   case kMenuRefSaveAs: {
703     if (SaveReferenceAs()) {
704       fMenuReference->DisableEntry(kMenuRefSave);
705     }
706     break;
707   }
708
709   case kMenuOptLoop: {
710     Float_t interval = fLoopInterval * 0.001;
711     new AliMonitorNumberDlg(interval, this, "Loop Interval",
712                             "loop time in seconds:", 0.1);
713     if (interval < 0) break;
714
715     fLoopInterval = Int_t(1000 * interval);
716     if (fLoopTimer) {
717       fLoopTimer->Stop();
718       fLoopTimer->Start(fLoopInterval);
719     }
720     break;
721   }
722
723   case kMenuOptPrint: {
724     TString printCommand(fPrintCommand);
725     new AliMonitorStringDlg(printCommand, this, "Print Command",
726                             "shell command for printing:");
727     if (printCommand.IsNull()) break;
728
729     fPrintCommand = printCommand;
730     break;
731   }
732
733   case kMenuOptSaveOnExit: {
734     if (fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit)) {
735       fMenuOptions->UnCheckEntry(kMenuOptSaveOnExit);
736     } else {
737       fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
738     }
739     break;
740   }
741
742   case kMenuOptSave: {
743     SaveSettings();
744     break;
745   }
746
747   case kMenuHelpAbout: {
748     Int_t result;
749     new TGMsgBox(gClient->GetRoot(), this, 
750                  "About", "AliMonitorClient $Revision$", 
751                  kMBIconAsterisk, kMBOk, &result);
752     break;
753   }
754
755   default: {
756     Int_t result;
757     new TGMsgBox(gClient->GetRoot(), this, 
758                  "AliMonitorClient", "not yet implemented", 
759                  kMBIconExclamation, kMBOk, &result);
760   }
761   }
762 }
763
764
765 //_____________________________________________________________________________
766 void AliMonitorClient::OnEventNumberChanged()
767 {
768 // called when the event number in the tool button was changed
769
770   if (!fRunButton->IsDown()) {
771     UpdateHisto();
772     UpdateComparisonTree();
773   }
774 }
775
776 //_____________________________________________________________________________
777 void AliMonitorClient::OnEventButtonPressed()
778 {
779 // called when the event tool button was clicked
780
781   fSumButton->SetDown(kFALSE);
782   fRunButton->SetDown(kFALSE);
783   UpdateHisto();
784   UpdateComparisonTree();
785 }
786
787 //_____________________________________________________________________________
788 void AliMonitorClient::OnSumButtonPressed()
789 {
790 // called when the sum tool button was clicked
791
792   fEventButton->SetDown(kFALSE);
793   fRunButton->SetDown(kFALSE);
794   UpdateHisto();
795   UpdateComparisonTree();
796 }
797
798 //_____________________________________________________________________________
799 void AliMonitorClient::OnRunButtonPressed()
800 {
801 // called when the run tool button was clicked
802
803   fEventButton->SetDown(kFALSE);
804   fSumButton->SetDown(kFALSE);
805   UpdateHisto();
806   UpdateComparisonTree();
807 }
808
809 //_____________________________________________________________________________
810 void AliMonitorClient::OnLoopButtonClicked()
811 {
812 // called when the loop tool button was clicked
813
814   // if loop is not running, start the loop timer and 
815   // set the stop loop button picture
816   if (!fLoopTimer) {  
817     if (!fBaseItem) {
818       if (!GetBaseItem()) return;
819     }
820     fLoopTimer = new TTimer(fLoopInterval);
821     fLoopTimer->Connect("Timeout()", "AliMonitorClient", this, 
822                         "OnLoopTimer()");
823     ((TGPictureButton*) fLoopButton)->SetPicture(fLoopOffPicture);
824     fLoopTimer->TurnOn();
825
826   // if the loop is running, stop it
827   } else {
828     StopLoop();
829   }
830 }
831
832 //_____________________________________________________________________________
833 void AliMonitorClient::OnPreviousButtonClicked()
834 {
835 // called when the previous tool button was clicked
836
837   if (!fBaseItem) {
838     if (!GetBaseItem()) return;
839   }
840   StopLoop();
841   GoToPreviousItem();
842 }
843
844 //_____________________________________________________________________________
845 void AliMonitorClient::OnNextButtonClicked()
846 {
847 // called when the next tool button was clicked
848
849   if (!fBaseItem) {
850     if (!GetBaseItem()) return;
851   }
852   StopLoop();
853   GoToNextItem();
854 }
855
856 //_____________________________________________________________________________
857 void AliMonitorClient::OnCopyButtonClicked()
858 {
859 // called when the copy tool button was clicked
860
861   fDrawCanvas->GetCanvas()->DrawClone();
862 }
863
864 //_____________________________________________________________________________
865 void AliMonitorClient::OnSaveButtonClicked()
866 {
867 // called when the save tool button was clicked
868
869   // display a file save dialog
870   static TGFileInfo fileInfo;
871   static const char* fileTypes[] = {"PostScript",   "*.ps",
872                                     "Encapsulated PostScript", "*.eps",
873                                     "SVG",          "*.svg",
874                                     "Gif files",    "*.gif",
875                                     "Macro files",  "*.C",
876                                     "ROOT files", "*.root", 
877                                     "All files",  "*", 
878                                     NULL,         NULL};
879   fileInfo.fFileTypes = fileTypes;
880   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
881   if (!fileInfo.fFilename) return;
882
883   fDrawCanvas->GetCanvas()->SaveAs(fileInfo.fFilename);
884 }
885
886 //_____________________________________________________________________________
887 void AliMonitorClient::OnPrintButtonClicked()
888 {
889 // called when the print tool button was clicked
890
891   // save the canvas to a temporary postscript file
892   char fileName[L_tmpnam+4];
893   sprintf(fileName, "%s.ps", tmpnam(NULL));
894   fDrawCanvas->GetCanvas()->SaveAs(fileName);
895
896   // call the print command and delete the temporary file
897   char command[256];
898   sprintf(command, "%s %s", fPrintCommand.Data(), fileName);
899   gSystem->Exec(command);
900   gSystem->Unlink(fileName);
901 }
902
903
904 //_____________________________________________________________________________
905 void AliMonitorClient::OnTreeClicked(TGListTreeItem* item, Int_t)
906 {
907 // called when an item in the histogram tree is clicked
908
909   OnTreeReturnPressed(item);
910 }
911
912 //_____________________________________________________________________________
913 void AliMonitorClient::OnTreeReturnPressed(TGListTreeItem* item)
914 {
915 // called when return is pressed at an item in the histogram tree
916
917   fCurrentItem = item;
918   fBaseItem = NULL;
919   StopLoop();
920   UpdateItem(kFALSE);
921 }
922
923
924 //_____________________________________________________________________________
925 void AliMonitorClient::OnLoopTimer()
926 {
927 // called by the loop timer when a new histogram should be displayed
928
929   if (!fBaseItem) {
930     if (!GetBaseItem()) return;
931   }
932   GoToNextItem();
933 }
934
935
936 //_____________________________________________________________________________
937 TFolder* AliMonitorClient::CreateTopFolder() const
938 {
939 // create a top folder for monitor histograms
940
941   return (new TFolder("Monitor", "monitor histograms"));
942 }
943
944 //_____________________________________________________________________________
945 AliMonitorHisto* AliMonitorClient::GetHisto(const char* folderName, 
946                                             const char* histoName)
947 {
948 // find the monitor histogram with the given name in the given folder
949
950   TGListTreeItem* folderItem = fTree->FindChildByName(fAllItem, folderName);
951   if (folderItem) {
952     TGListTreeItem* histoItem = fTree->FindChildByName(folderItem, histoName);
953     if (histoItem) return (AliMonitorHisto*) histoItem->GetUserData();
954   }
955   return NULL;
956 }
957
958 //_____________________________________________________________________________
959 TGListTreeItem* AliMonitorClient::GetItem(TGListTreeItem* base, 
960                                           const char* folderName, 
961                                           const char* histoName, 
962                                           Bool_t create)
963 {
964 // find the tree item with given name in the given folder
965 // if create is kTRUE it is created if it is not there
966
967   // get or create the folder
968   TGListTreeItem* folderItem = fTree->FindChildByName(base, folderName);
969   if (!folderItem) {
970     if (!create) return NULL;
971     folderItem = fTree->AddItem(base, folderName);
972   }
973
974   // get or create the histo
975   TGListTreeItem* histoItem = fTree->FindChildByName(folderItem, histoName);
976   if (!histoItem) {
977     if (!create) return NULL;
978     histoItem = fTree->AddItem(folderItem, histoName,
979                                fClient->GetPicture("h1_t.xpm"),
980                                fClient->GetPicture("h1_t.xpm"));
981   }
982   return histoItem;
983 }
984
985
986 //_____________________________________________________________________________
987 Bool_t AliMonitorClient::ConnectToServer()
988 {
989 // display the dialog for the server name or ip and try to connect to it
990
991   TString serverName(fServerName);
992
993   do {
994     // ask for the server name or ip
995     new AliMonitorStringDlg(serverName, this, "Connection to monitor process",
996                             "monitor server name or ip:");
997     if (serverName.IsNull()) return kFALSE;
998
999     // connect to the server
1000     fSocket = new TSocket(serverName, AliMonitorProcess::GetPort());
1001     if (!fSocket || !fSocket->IsValid() || (fSocket->Send("client") <= 0)) {
1002       if (fSocket) delete fSocket;
1003       fSocket = NULL;
1004       Int_t result;
1005       new TGMsgBox(gClient->GetRoot(), this, "Connect",
1006                    "connection to monitor server failed", 
1007                    kMBIconExclamation, kMBOk, &result);
1008
1009     } else {  // set up a handler for notifying when new data is there
1010       fServerName = serverName;
1011       fSocketHandler = new TFileHandler(fSocket->GetDescriptor(), 
1012                                         TFileHandler::kRead);
1013       fSocketHandler->Connect("Notified()", "AliMonitorClient", this,
1014                               "OnNewData()");
1015       fSocketHandler->Add();
1016       TInetAddress adr = fSocket->GetInetAddress();
1017       AliInfo(Form("connected to server: %s (%s), port %d",
1018                    adr.GetHostName(), adr.GetHostAddress(), adr.GetPort()));
1019       fMenuFile->HideEntry(kMenuFileConnect);
1020       fMenuFile->HideEntry(kMenuFileOpen);
1021       fMenuFile->EnableEntry(kMenuFileDisconnect);
1022     };
1023
1024   } while (!fSocket);
1025
1026   // delete the old monitor histos
1027   if (fFolder) delete fFolder;
1028   fFolder = CreateTopFolder();
1029   return kTRUE;
1030 }
1031
1032 //_____________________________________________________________________________
1033 void AliMonitorClient::DisconnectFromServer()
1034 {
1035 // disconnect from the monitor server
1036
1037   // are-you-really-sure-dialog
1038   Int_t result;
1039   new TGMsgBox(gClient->GetRoot(), this, "Disconnect",
1040                "Do you really want to disconnect from the monitor server?", 
1041                kMBIconQuestion, kMBYes | kMBNo, &result);
1042   if (result == kMBNo) return;
1043
1044   // disconnect from the server
1045   fSocketHandler->Remove();
1046   fSocket->Send("disconnect");
1047   fSocket->Close();
1048   delete fSocket;
1049   fSocket = NULL;
1050   fMenuFile->HideEntry(kMenuFileDisconnect);
1051   fMenuFile->EnableEntry(kMenuFileConnect);
1052   fMenuFile->EnableEntry(kMenuFileOpen);
1053 }
1054
1055 //_____________________________________________________________________________
1056 Bool_t AliMonitorClient::OpenFile()
1057 {
1058 // open a file with monitor histograms
1059
1060   // display a file open dialog
1061   static TGFileInfo fileInfo;
1062   static const char* fileTypes[] = {"ROOT files", "*.root", 
1063                                     "All files",  "*", 
1064                                     NULL,         NULL};
1065   fileInfo.fFileTypes = fileTypes;
1066   new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1067   if (!fileInfo.fFilename) return kFALSE;
1068
1069   // open the root file
1070   TFile* file = TFile::Open(fileInfo.fFilename);
1071   if (!file || !file->IsOpen()) {
1072     Int_t result;
1073     new TGMsgBox(gClient->GetRoot(), this, "Open",
1074                  "The file could not be opened.", 
1075                  kMBIconExclamation, kMBOk, &result);
1076     return kFALSE;
1077   }
1078
1079   // get the folder with the monitor histograms
1080   TFolder* folder = (TFolder*) file->Get("Monitor");
1081   if (!folder || !folder->InheritsFrom(TFolder::Class())) {
1082     Int_t result;
1083     new TGMsgBox(gClient->GetRoot(), this, "Open",
1084                  "The file does not contain monitor histograms.", 
1085                  kMBIconExclamation, kMBOk, &result);
1086     file->Close();
1087     delete file;
1088     return kFALSE;
1089   }
1090
1091   // replace the old folder with the new one
1092   file->Clear();
1093   file->Close();
1094   delete file;
1095   if (fFolder) delete fFolder;
1096   fFolder = folder;
1097   return kTRUE;
1098 }
1099
1100
1101 //_____________________________________________________________________________
1102 void AliMonitorClient::ViewToolBar(Bool_t visible)
1103 {
1104 // en- or disable the view of the tool bar
1105
1106   if (visible) {
1107     ShowFrame(fToolBarSep);
1108     ShowFrame(fToolBar);
1109     fMenuView->CheckEntry(kMenuViewToolBar);
1110   } else {
1111     HideFrame(fToolBarSep);
1112     HideFrame(fToolBar);
1113     fMenuView->UnCheckEntry(kMenuViewToolBar);
1114   }
1115 }
1116
1117 //_____________________________________________________________________________
1118 void AliMonitorClient::ViewTree(Bool_t visible)
1119 {
1120 // en- or disable the view of the tree
1121
1122   if (visible) {
1123     fHorizontalFrame->ShowFrame(fTreeFrame);
1124     fHorizontalFrame->ShowFrame(fTreeSplitter);
1125     fMenuView->CheckEntry(kMenuViewTree);
1126   } else {
1127     fHorizontalFrame->HideFrame(fTreeFrame);
1128     fHorizontalFrame->HideFrame(fTreeSplitter);
1129     fMenuView->UnCheckEntry(kMenuViewTree);
1130   }
1131 }
1132
1133 //_____________________________________________________________________________
1134 void AliMonitorClient::ViewDescription(Bool_t visible)
1135 {
1136 // en- or disable the view of the histogram description
1137
1138   if (visible) {
1139     fVerticalFrame->ShowFrame(fDescriptionFrame);
1140     fVerticalFrame->ShowFrame(fDescriptionSplitter);
1141     fMenuView->CheckEntry(kMenuViewDescription);
1142   } else {
1143     fVerticalFrame->HideFrame(fDescriptionFrame);
1144     fVerticalFrame->HideFrame(fDescriptionSplitter);
1145     fMenuView->UnCheckEntry(kMenuViewDescription);
1146   }
1147 }
1148
1149 //_____________________________________________________________________________
1150 void AliMonitorClient::ViewReference(Bool_t visible)
1151 {
1152 // en- or disable the view of the reference histos
1153
1154   if (visible) {
1155     AliMonitorHisto::SetDrawRef(kTRUE);
1156     fMenuView->CheckEntry(kMenuViewReference);
1157   } else {
1158     AliMonitorHisto::SetDrawRef(kFALSE);
1159     fMenuView->UnCheckEntry(kMenuViewReference);
1160   }
1161 }
1162
1163 //_____________________________________________________________________________
1164 void AliMonitorClient::ViewStatistics(Bool_t visible)
1165 {
1166 // en- or disable the view of the statistics box
1167
1168   if (visible) {
1169     gStyle->SetOptStat(1110);
1170     fMenuView->CheckEntry(kMenuViewStatistics);
1171   } else {
1172     gStyle->SetOptStat(0);
1173     fMenuView->UnCheckEntry(kMenuViewStatistics);
1174   }
1175 }
1176
1177
1178 //_____________________________________________________________________________
1179 Bool_t AliMonitorClient::AddFavorite()
1180 {
1181 // add the current histogram or folder to the list of favorites
1182
1183   if (!fCurrentItem || !fCurrentItem->GetParent()) return kFALSE;
1184
1185   // get the folder item
1186   TGListTreeItem* folderItem = fCurrentItem->GetParent();
1187   if (fCurrentItem->GetFirstChild()) folderItem = fCurrentItem;
1188
1189   Bool_t result = kFALSE;
1190
1191   // add a folder
1192   if (fCurrentItem->GetFirstChild()) {
1193     TGListTreeItem* histoItem = fCurrentItem->GetFirstChild();
1194     while (histoItem) {
1195       if (!GetItem(fFavoritesItem, folderItem->GetText(), 
1196                    histoItem->GetText(), kFALSE)) result = kTRUE;
1197       TGListTreeItem* item = GetItem(fFavoritesItem, folderItem->GetText(), 
1198                                      histoItem->GetText(), kTRUE);
1199       item->SetUserData(histoItem->GetUserData());
1200       histoItem = histoItem->GetNextSibling();
1201     }
1202
1203   // add a histo
1204   } else {
1205     if (!GetItem(fFavoritesItem, folderItem->GetText(), 
1206                  fCurrentItem->GetText(), kFALSE)) result = kTRUE;
1207     TGListTreeItem* item = GetItem(fFavoritesItem, folderItem->GetText(), 
1208                                    fCurrentItem->GetText(), kTRUE);
1209     item->SetUserData(fCurrentItem->GetUserData());
1210   }
1211
1212   if (result) gClient->NeedRedraw(fTree);
1213   return result;
1214 }
1215
1216 //_____________________________________________________________________________
1217 Bool_t AliMonitorClient::DeleteFavorite()
1218 {
1219 // delete the current histogram or folder from the list of favorites
1220
1221   // check that the current item is a favorites histo or folder
1222   if (!fCurrentItem || !fCurrentItem->GetParent()) return kFALSE;
1223   TGListTreeItem* base = fCurrentItem;
1224   while (base->GetParent()) base = base->GetParent();
1225   if (base != fFavoritesItem) return kFALSE;
1226
1227   // delete it
1228   TGListTreeItem* parent = fCurrentItem->GetParent();
1229   fTree->DeleteItem(fCurrentItem);
1230   fCurrentItem = NULL;
1231
1232   // delete the parent folder if it is empty now
1233   if (parent->GetParent() != NULL) {
1234     if (!parent->GetFirstChild()) fTree->DeleteItem(parent);
1235   }
1236
1237   gClient->NeedRedraw(fTree);
1238   return kTRUE;
1239 }
1240
1241 //_____________________________________________________________________________
1242 Bool_t AliMonitorClient::LoadFavorites(Bool_t dialog)
1243 {
1244 // load the list of favorites from a file
1245
1246   // display a file open dialog
1247   TGFileInfo fileInfo;
1248   static const char* fileTypes[] = {"Favorites files", "*.fav", 
1249                                     "All files",  "*", 
1250                                     NULL,         NULL};
1251   fileInfo.fFileTypes = fileTypes;
1252   fileInfo.fIniDir = StrDup(".");
1253   fileInfo.fFilename = StrDup(fFavoritesFileName.Data());
1254   if (dialog) {
1255     new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1256     if (!fileInfo.fFilename) return kFALSE;
1257   }
1258
1259   // open the text file
1260   FILE* file = fopen(fileInfo.fFilename, "rt");
1261   if (!file) {
1262     Int_t result;
1263     new TGMsgBox(gClient->GetRoot(), this, "Load Favorites",
1264                  "The file could not be opened.", 
1265                  kMBIconExclamation, kMBOk, &result);
1266     return kFALSE;
1267   }
1268
1269   // delete the old favorites
1270   TGListTreeItem* favFolderItem = fFavoritesItem->GetFirstChild();
1271   while (favFolderItem) {
1272     TGListTreeItem* deleteItem = favFolderItem;
1273     favFolderItem = favFolderItem->GetNextSibling();
1274     fTree->DeleteItem(deleteItem);
1275   }
1276
1277   // scan the text file and add the favorites histos
1278   char buffer[256];
1279   while (!feof(file)) {
1280     if (fgets(buffer, 255, file) == NULL) break;
1281     char* folder = strtok(buffer, "/");
1282     char* item = strtok(NULL, "\n");
1283     if (item[strlen(item)-1] == '\n') item[strlen(item)-1] = 0;
1284     if (!folder || !item) continue;
1285
1286     AliMonitorHisto* histo = GetHisto(folder, item);
1287     TGListTreeItem* histoItem = GetItem(fFavoritesItem, folder, item, kTRUE);
1288     histoItem->SetUserData(histo);
1289   }
1290   fclose(file);
1291
1292   return kTRUE;
1293 }
1294
1295 //_____________________________________________________________________________
1296 Bool_t AliMonitorClient::SaveFavorites()
1297 {
1298 // save the list of favorites in a file with the name fFavoritesFileName
1299
1300   // if no file name is given use a default one
1301   if (fFavoritesFileName.IsNull()) {
1302     char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1303                                              "AliMonitorClient.fav");
1304     fFavoritesFileName = fileName;
1305     free(fileName);
1306   }
1307
1308   // open the text file
1309   FILE* file = fopen(fFavoritesFileName.Data(), "wt");
1310   if (!file) {
1311     Int_t result;
1312     new TGMsgBox(gClient->GetRoot(), this, "Save Favorites",
1313                  "The file could not be opened.", 
1314                  kMBIconExclamation, kMBOk, &result);
1315     return kFALSE;
1316   }
1317
1318   // loop over folders
1319   TGListTreeItem* folderItem = fFavoritesItem->GetFirstChild();
1320   while (folderItem) {
1321
1322     // loop over histos
1323     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1324     while (histoItem) {
1325
1326       // write the favorites
1327       if (fprintf(file, "%s/%s\n", folderItem->GetText(), 
1328                   histoItem->GetText()) <= 0) {
1329         Int_t result;
1330         new TGMsgBox(gClient->GetRoot(), this, "Save Favorites",
1331                      "An error occured while sving the favorites.", 
1332                      kMBIconExclamation, kMBOk, &result);
1333         fclose(file);
1334         return kFALSE;
1335       }
1336       histoItem = histoItem->GetNextSibling();
1337     }
1338
1339     folderItem = folderItem->GetNextSibling();
1340   }
1341
1342   fclose(file);
1343   AliInfo(Form("favorites saved to file %s", 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   AliInfo(Form("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   AliDebug(1, Form("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   AliInfo(Form("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   // disable the socket handler in this method
1877   if (!fSocket || !fSocket->IsValid()) return kFALSE;
1878   fSocketHandler->Remove();
1879
1880   // receive a control message from the server
1881   char controlMessage[256];
1882   if (fSocket->Recv(controlMessage, 255) <= 0) {
1883     fSocketHandler->Add();
1884     return kFALSE;
1885   }
1886
1887   // if it is new histogram data, send ok
1888   if ((strcmp(controlMessage, "histograms") != 0) ||
1889       (fSocket->Send("ok") <= 0)) {
1890     fSocketHandler->Add();
1891     return kFALSE;
1892   }
1893
1894   // get the histogram data
1895   TMessage* message = NULL;
1896   if (fSocket->Recv(message) <= 0) {
1897     fSocketHandler->Add();
1898     return kFALSE;
1899   }
1900
1901   // replace the old folder of monitor histos with the new one
1902   if (message->GetClass()->InheritsFrom(TFolder::Class())) {
1903     if (fFolder) delete fFolder;
1904     fFolder = (TFolder*) message->ReadObject(message->GetClass());
1905     delete message;
1906     fSocketHandler->Add();
1907     return kTRUE;
1908   }
1909
1910   delete message;
1911   fSocketHandler->Add();
1912   return kFALSE;
1913 }
1914
1915 //_____________________________________________________________________________
1916 void AliMonitorClient::ClearItems(TGListTreeItem* base) const
1917 {
1918 // remove the references to the histograms from all subitems of the 
1919 // given tree item
1920
1921   // loop over folders
1922   TGListTreeItem* folderItem = base->GetFirstChild();
1923   while (folderItem) {
1924
1925     // loop over histos
1926     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1927     while (histoItem) {
1928       histoItem->SetUserData(NULL);
1929       histoItem = histoItem->GetNextSibling();
1930     }
1931
1932     folderItem = folderItem->GetNextSibling();
1933   }
1934 }
1935
1936 //_____________________________________________________________________________
1937 void AliMonitorClient::CleanUpTree(TGListTreeItem* base)
1938 {
1939 // remove items without monitor histograms and 
1940 // folders without monitor histograms
1941
1942   // loop over folders
1943   TGListTreeItem* folderItem = base->GetFirstChild();
1944   while (folderItem) {
1945
1946     // loop over histos
1947     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1948     while (histoItem) {
1949       TGListTreeItem* deleteItem = NULL;
1950       if (!histoItem->GetUserData()) deleteItem = histoItem;
1951       histoItem = histoItem->GetNextSibling();
1952       if (fCurrentItem == deleteItem) fCurrentItem = NULL;
1953       if (deleteItem) fTree->DeleteItem(deleteItem);
1954     }
1955
1956     folderItem = folderItem->GetNextSibling();
1957   }
1958
1959   // loop over folders and remove empty folders
1960   folderItem = base->GetFirstChild();
1961   while (folderItem) {
1962     TGListTreeItem* deleteItem = NULL;
1963     if (!folderItem->GetFirstChild()) deleteItem = folderItem;
1964     folderItem = folderItem->GetNextSibling();
1965     if (fCurrentItem == deleteItem) fCurrentItem = NULL;
1966     if (deleteItem) fTree->DeleteItem(deleteItem);
1967   }
1968 }
1969
1970 //_____________________________________________________________________________
1971 void AliMonitorClient::UpdateTree()
1972 {
1973 // update the tree of monitor histograms
1974
1975   // delete references to old monitor histograms
1976   ClearItems(fAllItem);
1977
1978   // loop over folder
1979   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
1980   while (TFolder* folder = (TFolder*) iFolder->Next()) {
1981
1982     // loop over histos
1983     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
1984     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
1985
1986       // add new monitor histograms
1987       TGListTreeItem* histoItem = GetItem(fAllItem, folder->GetName(),
1988                                           histo->GetName(), kTRUE);
1989       histoItem->SetUserData(histo);
1990     }
1991     delete iHisto;
1992
1993   }
1994   delete iFolder;
1995
1996   // remove items and folders without monitor histograms
1997   CleanUpTree(fAllItem);
1998
1999   gClient->NeedRedraw(fTree);
2000 }
2001
2002 //_____________________________________________________________________________
2003 void AliMonitorClient::UpdateFavoritesTree()
2004 {
2005 // update the tree of favorite monitor histograms
2006
2007   // loop over folders
2008   TGListTreeItem* folderItem = fFavoritesItem->GetFirstChild();
2009   while (folderItem) {
2010
2011     // loop over histos
2012     TGListTreeItem* histoItem = folderItem->GetFirstChild();
2013     while (histoItem) {
2014
2015       // set monitor histo
2016       histoItem->SetUserData(GetHisto(folderItem->GetText(), 
2017                                       histoItem->GetText()));
2018       histoItem = histoItem->GetNextSibling();
2019     }
2020
2021     folderItem = folderItem->GetNextSibling();
2022   }
2023 }
2024
2025 //_____________________________________________________________________________
2026 void AliMonitorClient::UpdateComparisonTree()
2027 {
2028 // update the tree of monitor histograms with significant deviation
2029 // from the reference histograms
2030
2031   if (!fFolder) return;
2032
2033   // delete references to old monitor histograms
2034   ClearItems(fComparisonItem);
2035
2036   // add monitor histograms where the comparison returns a deviation
2037   // loop over folders
2038   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
2039   while (TFolder* folder = (TFolder*) iFolder->Next()) {
2040
2041     // loop over histos
2042     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
2043     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
2044
2045       // compare the histo to its reference
2046       Bool_t comparison = kTRUE;
2047       if (fEventButton->IsDown()) {
2048         comparison = histo->CompareEvent(fEventNumber->GetIntNumber());
2049       } else if (fSumButton->IsDown()) {
2050         comparison = histo->CompareSum(fEventNumber->GetIntNumber());
2051       } else {
2052         comparison = histo->CompareRun();
2053       }
2054
2055       // add it to the comparison tree in case of a bad comparison result
2056       if (!comparison) {
2057         TGListTreeItem* histoItem = GetItem(fComparisonItem, folder->GetName(),
2058                                             histo->GetName(), kTRUE);
2059         histoItem->SetUserData(histo);
2060       }
2061     }
2062     delete iHisto;
2063
2064   }
2065   delete iFolder;
2066
2067   // remove items and folders without monitor histograms
2068   CleanUpTree(fComparisonItem);
2069
2070   gClient->NeedRedraw(fTree);
2071 }
2072
2073 //_____________________________________________________________________________
2074 void AliMonitorClient::UpdateDescription()
2075 {
2076 // update the description of the current monitor histogram
2077
2078   fDescription->Clear();
2079   AliMonitorHisto* histo = NULL;
2080   if (fCurrentItem) histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
2081   if (histo) fDescription->LoadBuffer(histo->GetDescription().Data());
2082
2083   gClient->NeedRedraw(fDescription);
2084 }
2085
2086 //_____________________________________________________________________________
2087 void AliMonitorClient::UpdateHisto()
2088 {
2089 // update the current monitor histogram
2090
2091   // clear the canvas if no histo is selected
2092   AliMonitorHisto* histo = NULL;
2093   if (fCurrentItem) histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
2094   if (!histo) {
2095     fDrawCanvas->GetCanvas()->Clear();
2096     fDrawCanvas->GetCanvas()->Update();
2097     return;
2098   }
2099
2100   // draw the histo for a single event or summed over several events or a run
2101   fDrawCanvas->GetCanvas()->cd();
2102   if (fEventButton->IsDown()) {
2103     histo->DrawEvent(fEventNumber->GetIntNumber());
2104   } else if (fSumButton->IsDown()) {
2105     histo->DrawSum(fEventNumber->GetIntNumber());
2106   } else {
2107     histo->DrawRun();
2108   }
2109 }
2110
2111 //_____________________________________________________________________________
2112 void AliMonitorClient::UpdateAll()
2113 {
2114 // update the trees, the histogram and the description
2115
2116   UpdateTree();
2117   UpdateFavoritesTree();
2118   UpdateComparisonTree();
2119   UpdateDescription();
2120   UpdateHisto();
2121 }
2122