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