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