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