Index: /fact/Evidence/GUI.cc
===================================================================
--- /fact/Evidence/GUI.cc	(revision 12939)
+++ /fact/Evidence/GUI.cc	(revision 12940)
@@ -23,13 +23,10 @@
   QString Format;
   DimBrowser Browser;
-  class EvidenceHistory *Hist = Handler->GetHistory(Service);
+  struct EddDim::HistItem Hist = Handler->GetHistory(Service);
   char *Name, *Fmt;
 
   // Check if history service available
   if (strcmp(Service, "Edd/Rate_kBSec") == 0) Format = "F";
-  else if (Hist == NULL || Hist->GetFormat() == NULL) {
-	printf("Edd Message: Could not retrieve history for service %s\n", Service);
-  }
-  else Format = Hist->GetFormat();
+  else Format = Hist.Format;
   
   // If service currently available, take its format
@@ -37,6 +34,4 @@
   if (Browser.getNextService(Name, Fmt) != 0) Format = QString(Fmt);
 
-  Handler->DropHistory(Service);
-  
   // Open new window  	
   QMainWindow *M = new QMainWindow;
@@ -51,12 +46,9 @@
   else  {
     EddPlot *W = new EddPlot(Service, FromIndex);
-	for (int i=FromIndex+1; i<=ToIndex; i++) {
-	  W->AddService(Service,i);
-      Layout->addWidget(new EddLineDisplay(Service, i), 1 + (i-FromIndex)/5, (i-FromIndex)%5);
-	}
+	for (int i=FromIndex+1; i<=ToIndex; i++) W->AddService(Service,i);
+ 
 	Layout->addWidget(W, 0, 0, 1, 5);
   }
   
-  Layout->addWidget(new EddLineDisplay(Service, FromIndex), 1, 0);
   M->resize(400,450);
   M->show();
@@ -70,5 +62,5 @@
   QString Status;
 
-  if (Index != -1) Name = Name + "[" + QString::number(Index) + "]";
+  if (Index != -1) Name = Name + ":" + QString::number(Index);
 
   if (Time == -1) Status = QString("%1:  unavailable").arg(Name);
@@ -332,7 +324,4 @@
   connect(axisWidget(QwtPlot::xBottom), SIGNAL(scaleDivChanged()), SLOT(update()));
 
-  legend()->setItemMode(QwtLegend::ClickableItem);
-  connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
-  
   // Additonal context menu items
   QAction* Action = Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
@@ -344,4 +333,7 @@
   Action = Menu->addAction("Show last day", this, SLOT(MenuShowLastDay())); 
   Menu->insertAction(Menu->actions().value(8), Action);  
+
+  Action = Menu->addAction("All as text", this, SLOT(MenuAllAsText())); 
+  Menu->insertAction(Menu->actions().value(10), Action); 
    
   // Set timer to regularly update plot if new data available
@@ -357,8 +349,8 @@
 EddPlot::~EddPlot() {
 
-  while (!List.isEmpty()) DeleteCurve(List.last().Signal);
-}
-
-// Add history service to plot
+  while (!List.isEmpty()) RemoveService(List.last().Curve);
+}
+
+// Add service to plot
 void EddPlot::AddService(QString Name, int Index) {
 
@@ -375,23 +367,25 @@
 
   N.Name = Name;
-  N.Signal = NewCurve(Name+"["+QString::number(Index)+"]");
   N.Index = Index;
+  N.Curve = NewCurve(Name+":"+QString::number(Index));
   List.append(N);
 
-  // Request new history buffer
-  const struct EvidenceHistory::Item *R;
-  class EvidenceHistory *Hist;
-
-  if ((Hist = Handler->GetHistory(Name)) != NULL) {
-	double Number=0;
-	while ((R=Hist->Next()) != NULL) {
-	  std::vector<std::string> Data = EvidenceServer::Tokenize(EvidenceServer::ToString(Hist->GetFormat(), R->Data, R->Size));
-	  if (N.Index > 0 && N.Index < (int) Data.size()) Number = atof(Data[N.Index].c_str());
-	  AddPoint(List.size()-1, R->Time, Number);
-	}
-  }
-  Handler->DropHistory(Name);
+  // Use custom legend widget
+  EddLegend *Legend = new EddLegend(N.Curve, this);
+  legend()->remove(N.Curve);
+  legend()->insert(N.Curve, (QWidget *) Legend);
+  
+  // Context menu might delete curve and legend -> seg fault if using direct connection, as legend item deleted
+  connect(Legend, SIGNAL(DeleteCurve(QwtPlotCurve *)), this, SLOT(RemoveService(QwtPlotCurve *)), Qt::QueuedConnection);
+
+  // Get history
+  struct EddDim::HistItem Hist = Handler->GetHistory(Name);
+
+  for (int i=0; i<Hist.DataText.size(); i++) {
+	AddPoint(List.size()-1, Hist.DataText[i].first, Hist.DataText[i].second.at(N.Index).toFloat());
+  }
+
+  // Subscribe to service and start updating plot after 100 ms (to allow addition of other curves)
   Handler->Subscribe(Name, this, Index);
-  
   SingleShot->start(100);
 }
@@ -407,5 +401,4 @@
   }
 }
-
 
 // Add text indicating time range to plot
@@ -435,17 +428,4 @@
 }
 
-void EddPlot::LegendClicked(QwtPlotItem *Item) {
-
-  QString D(Item->title().text());
-  D.replace('(',' ').chop(1);
-  
-  QDrag *Drag = new QDrag(this);
-  QMimeData *MimeData = new QMimeData;
-  QByteArray Data;
-  MimeData->setData("Edd/Service", Data.append(D));
-  Drag->setMimeData(MimeData);
-  Drag->exec();
-}
-
 // Add new service by pasting name
 void EddPlot::MenuPasteService() {
@@ -462,5 +442,4 @@
 
   setAxisScale(QwtPlot::xBottom, time(NULL)-60*60, time(NULL)+60);
-  //setAxisAutoScale(QwtPlot::yLeft);
   replot();
 }
@@ -469,16 +448,35 @@
 
   setAxisScale(QwtPlot::xBottom, time(NULL)-24*3600, time(NULL)+3600);
-  //setAxisAutoScale(QwtPlot::yLeft);
   replot();
 }
 
-
-// Remove list entry
-void EddPlot::DeleteCurve(QwtPlotCurve *Curve) {
-
-  for (int i=0; i<List.size(); i++) if (List[i].Signal == Curve) {
-    Handler->Unsubscribe(List[i].Name, this, List[i].Index);
-    List.removeAt(i);
-  }
+void EddPlot::MenuAllAsText() {
+
+  QMainWindow *M = new QMainWindow;
+  M->setCentralWidget(new QWidget(M));
+  M->setStatusBar(new QStatusBar(M));
+  M->setAttribute(Qt::WA_DeleteOnClose);
+  M->setWindowTitle("Edd Services");
+
+  QGridLayout *Layout = new QGridLayout(M->centralWidget());
+
+  for (int i=0; i<List.size(); i++) {
+      Layout->addWidget(new EddLineDisplay(List[i].Name, List[i].Index), i/10, i%10);
+  }
+
+  M->resize(400,450);
+  M->show();
+}
+
+
+// Remove subscription
+void EddPlot::RemoveService(QwtPlotCurve *Curve) {
+
+  for (int i=0; i<List.size(); i++) if (List[i].Curve == Curve) {
+	Handler->Unsubscribe(List[i].Name, this, List[i].Index);
+	List.removeAt(i);
+	DeleteCurve(Curve);
+	break;
+  }  
 }
 
@@ -543,5 +541,4 @@
   StatisticsAction->setCheckable(true);
   Menu->addAction("Zoom out", this, SLOT(MenuZoomOut()));
-  Menu->addAction("Single trace", this, SLOT(MenuSingleTrace()));
   Menu->addSeparator();
   Menu->addAction("Set update rate", this, SLOT(MenuSetUpdateRate()));  
@@ -561,5 +558,4 @@
 EddBasePlot::~EddBasePlot() {
 
-  for (int i=0; i<Items.size(); i++) delete Items[i].Signal;
   delete Grid;
 }
@@ -739,4 +735,7 @@
   // Selection region outside all axis?
   if (R.right() < 0 && R.top() > plotLayout()->canvasRect().height()) return;
+
+  // If selected rectangle completely inside canvas taken care of by zoomer
+  if (plotLayout()->canvasRect().contains(P.boundingRect())) return;
   
   // Rescale both axis if selected rectangle encompasses canvas completely
@@ -803,11 +802,12 @@
 }
 
-// Remove all items except one
-void EddBasePlot::MenuSingleTrace() {
-
-  while (Items.size() > 1) {  
-	DeleteCurve(Items.last().Signal);
-    delete Items.last().Signal;
-    Items.takeLast();
+
+// Remove item
+void EddBasePlot::DeleteCurve(QwtPlotCurve *Curve) {
+
+  for (int i=0; i<Items.size(); i++) if (Items[i].Signal == Curve) {
+	delete Curve;
+	Items.takeAt(i);
+	break;
   }
   UpdatePlot();
@@ -893,4 +893,109 @@
 }
 
+
+////////////////
+// Edd Legend //
+////////////////
+
+EddLegend::EddLegend(QwtPlotCurve *Curve, EddPlot *Plot): Curve(Curve), Plot(Plot) {
+
+  // Context menu
+  Menu = new QMenu(this);
+  Menu->addAction("Open in new history", this, SLOT(MenuOpenHistory()));
+  Menu->addAction("Copy service", this, SLOT(MenuCopyService()));
+  Menu->addAction("Normal line", this, SLOT(MenuNormalLine()));
+  Menu->addAction("Thick line", this, SLOT(MenuThickLine()));
+  Menu->addAction("Remove curve", this, SLOT(MenuRemove()));
+}
+
+//
+// Opening context menu
+//
+void EddLegend::contextMenuEvent(QContextMenuEvent *Event) {
+ 
+  Menu->exec(Event->globalPos());
+}
+
+// Handling of mouse press event: Register start position for drag
+void EddLegend::mousePressEvent(QMouseEvent *Event) {
+
+  if (Event->button() == Qt::LeftButton) dragStart = Event->pos();
+}
+
+// Handling of dragging (Drag and MimeData will be deleted by Qt)
+void EddLegend::mouseMoveEvent(QMouseEvent *Event) {
+
+  if ((Event->buttons() & Qt::LeftButton) == 0) return;
+  if ((Event->pos()-dragStart).manhattanLength() < QApplication::startDragDistance()) return;
+
+  QString D(text().text());
+  D.replace(':',' ');
+
+  QDrag *Drag = new QDrag(this);
+  QMimeData *MimeData = new QMimeData;
+  QByteArray Data;
+  MimeData->setData("Edd/Service", Data.append(D));
+  Drag->setMimeData(MimeData);
+  Drag->exec();
+}
+
+// Handling of mouse release event: Open history
+void EddLegend::mouseReleaseEvent(QMouseEvent *Event) {
+
+  if (Event->button() != Qt::LeftButton) return;
+  
+  QString D(text().text());
+  D.replace(':',' ');
+  QStringList A = D.split(" ");
+  
+  OpenHistory(A[0].toAscii().data(), A[1].toInt());
+}
+
+// Menu: Open history plot
+void EddLegend::MenuOpenHistory() {
+
+  QString D(text().text());
+  D.replace(':',' ');
+  QStringList A = D.split(" ");
+  
+  OpenHistory(A[0].toAscii().data(), A[1].toInt());
+}
+
+// Menu: Copy service name
+void EddLegend::MenuCopyService() {
+
+  QString D(text().text());
+  D.replace(':',' ');
+  
+  QMimeData *MimeData = new QMimeData;
+  QByteArray Data;
+  MimeData->setData("Edd/Service", Data.append(D));
+  QApplication::clipboard()->setMimeData(MimeData);
+}
+
+// Menu: Normal line width
+void EddLegend::MenuNormalLine() {
+
+  QPen Pen = Curve->pen();
+  Pen.setWidth(1);
+  Curve->setPen(Pen);
+  Curve->plot()->replot();
+}
+
+// Menu: Normal line width
+void EddLegend::MenuThickLine() {
+
+  QPen Pen = Curve->pen();
+  Pen.setWidth(4);
+  Curve->setPen(Pen);
+  Curve->plot()->replot();
+}
+
+// Menu: Normal line width
+void EddLegend::MenuRemove() {
+
+  emit(DeleteCurve(Curve));
+}
+
 //////////////////////////////////////
 // History text box for DIM service //
@@ -905,21 +1010,17 @@
   setAttribute(Qt::WA_DeleteOnClose);
   setAutoFillBackground(true);
-  setText("connecting...");
+  //setText("connecting...");
   document()->setMaximumBlockCount(1000);
   Accumulate = true;
   
+  // Get history for this service
   if (!Pure) {
-	// Get history for this service
-	const struct EvidenceHistory::Item *R;
-	class EvidenceHistory *Hist;
-
-	if ((Hist = Handler->GetHistory(Name)) != NULL) {
-	  while ((R=Hist->Next()) != NULL) {
-		moveCursor (QTextCursor::Start);
-		insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") " +
-		  QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), (void *) R->Data, R->Size)) + "\n"); 
-	  }	
-	}
-	Handler->DropHistory(Name);
+	struct EddDim::HistItem Hist = Handler->GetHistory(Name);
+	
+	for (int i=0; i<Hist.DataText.size(); i++) {
+	  moveCursor (QTextCursor::Start);
+	  insertPlainText(QString("(")+QDateTime::fromTime_t(Hist.DataText[i].first).toString()+") " +
+		  QString(Hist.DataRaw[i].second) + "\n"); 
+	}	
   }
 
@@ -987,6 +1088,4 @@
 EddDim::~EddDim() {
 
-  QList<QString> L = HistoryList.keys();
-  for(int i=0; i<L.size(); i++) delete HistoryList[L[i]].HistClass;
   delete Mutex;
 }
@@ -1043,38 +1142,30 @@
 
   QMutexLocker Locker(&IgnoreMutex);
-
   IgnoreMap[Name] = Ignore;
 }
 
 // Get history buffer
-class EvidenceHistory *EddDim::GetHistory(QString Name) {
-
-  // History already available (only request again if too old)
-  if (HistoryList.contains(Name)) {
-	HistoryList[Name].Count++;
-
-	if (time(NULL)-HistoryList[Name].LastUpdate < 5) {
-	  HistoryList[Name].HistClass->Rewind();
-	  return HistoryList[Name].HistClass;
-	}
-	HistoryList[Name].LastUpdate = time(NULL);
-	if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
-	else return NULL;
-  }
-
-  // Create new history class
-  HistoryList[Name].HistClass = new EvidenceHistory(Name.toStdString());
-  HistoryList[Name].Count = 1;
-  HistoryList[Name].LastUpdate = time(NULL);
-
-  if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
-  else return NULL;
-}
-
-// Reduce history usage counter
-void EddDim::DropHistory(QString Name) {
-
-  if (HistoryList.contains(Name)) HistoryList[Name].Count--;
-}
+struct EddDim::HistItem EddDim::GetHistory(QString Name) {
+
+  // History already available?
+  if (HistoryList.contains(Name)) return HistoryList[Name];
+
+  // Create history class to retrieve history data
+  const struct EvidenceHistory::Item *R;
+  class EvidenceHistory *Hist  = new EvidenceHistory(Name.toStdString());
+  Hist->GetHistory();
+  HistoryList[Name].Time = time(NULL);
+  HistoryList[Name].Format = Hist->GetFormat();
+
+  while ((R = Hist->Next()) != NULL) {
+	HistoryList[Name].DataRaw.push_back(QPair<int, QByteArray>(R->Time, QByteArray(R->Data, R->Size)));
+	HistoryList[Name].DataText.push_back(QPair<int, QStringList>(R->Time, QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), R->Data, R->Size)).split(' ')));
+  }
+  
+  delete Hist;
+
+  return HistoryList[Name];
+}
+
 
 // Update throughput statistics and clear up history memory
@@ -1087,8 +1178,5 @@
   QList<QString> L = HistoryList.keys();
   for(int i=0; i<L.size(); i++) {
-	if ((HistoryList[L[i]].Count <= 0) && (time(NULL)-HistoryList[L[i]].LastUpdate) > 5) { 
-	  delete HistoryList[L[i]].HistClass;
-	  HistoryList.remove(L[i]);
-	}
+	if ((time(NULL)-HistoryList[L[i]].Time) > 60) HistoryList.remove(L[i]);
   }
   
Index: /fact/Evidence/GUI.h
===================================================================
--- /fact/Evidence/GUI.h	(revision 12939)
+++ /fact/Evidence/GUI.h	(revision 12940)
@@ -11,4 +11,5 @@
 #include <qwt_plot_magnifier.h>
 #include <qwt_plot_panner.h>
+#include <qwt_picker_machine.h>
 #include <qwt_scale_engine.h>
 #include <qwt_analog_clock.h>
@@ -40,4 +41,5 @@
   	virtual void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int=-1) = 0;
 };
+
 
 // Base class for Edd plot
@@ -82,7 +84,7 @@
 	bool NewData;
 	QwtPlotCurve *NewCurve(QwtText);
+	void DeleteCurve(QwtPlotCurve *);
 	void ClearCurve(unsigned int);
 	void AddPoint(unsigned int, double, double);
-	virtual void DeleteCurve(QwtPlotCurve *) = 0;
 
   protected slots:
@@ -94,5 +96,4 @@
 	void MouseSelection(const QwtPolygon &);
 	void contextMenuEvent(QContextMenuEvent *);
-    void MenuSingleTrace();        
     void MenuSetUpdateRate();        
     void MenuZoomOut();
@@ -180,5 +181,5 @@
       QString Name;
 	  int Index;
-      QwtPlotCurve *Signal;	  
+	  QwtPlotCurve *Curve;
     };
     QList<struct ItemDetails> List;
@@ -187,4 +188,5 @@
 	QwtLegend *Legend;
 	QTimer *SingleShot;
+    QPoint dragStart;
 
     void dragEnterEvent(QDragEnterEvent *);
@@ -196,14 +198,44 @@
     ~EddPlot();
     void AddService(QString, int = 0);
-	void DeleteCurve(QwtPlotCurve *);
 	void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int = -1);
 
-  private slots:
-	void LegendClicked(QwtPlotItem *);
+  public slots:
+	void RemoveService(QwtPlotCurve *);
+
+  private slots:
     void MenuPasteService();
 	void MenuShowLastHour();
 	void MenuShowLastDay();
-};
-
+	void MenuAllAsText();
+};
+
+
+// Legend
+class EddLegend: public QwtLegendItem {
+    Q_OBJECT
+
+    QMenu *Menu;
+    QPoint dragStart;
+	QwtPlotCurve *Curve;
+	EddPlot *Plot;
+
+  public:
+	EddLegend(QwtPlotCurve *, EddPlot *);
+
+	void contextMenuEvent(QContextMenuEvent *);
+	void mousePressEvent(QMouseEvent *);
+	void mouseReleaseEvent(QMouseEvent *);
+    void mouseMoveEvent(QMouseEvent *);
+	
+  private slots:
+	void MenuOpenHistory();
+	void MenuCopyService();
+	void MenuNormalLine();
+	void MenuThickLine();
+	void MenuRemove();
+	
+  signals:
+	void DeleteCurve(QwtPlotCurve *);
+};
 
 // Text history and output class
@@ -227,4 +259,12 @@
 class EddDim: public QObject, public DimInfo {
   Q_OBJECT
+
+  public:
+	struct HistItem {
+	  int Time;
+	  QVector<QPair<int, QByteArray> > DataRaw;
+	  QVector<QPair<int, QStringList> > DataText;
+	  QString Format;
+	};
 
   private:
@@ -238,13 +278,8 @@
 	  QStringList Items;
 	};
+
     QMap<QString, struct Item> ServiceList;
 	QMap<QString, bool> IgnoreMap;
     QMutex *Mutex, IgnoreMutex;
-
-	struct HistItem {
-	  int Count;
-	  int LastUpdate;
-	  class EvidenceHistory *HistClass;
-	};
     QMap<QString, struct HistItem> HistoryList;
 
@@ -265,6 +300,5 @@
 	void Unsubscribe (QString, class EddWidget *, int = -1);
 	void Ignore (QString, bool);
-	class EvidenceHistory *GetHistory(QString);
-	void DropHistory(QString);
+	struct HistItem GetHistory(QString);
 
   signals:
Index: /fact/Evidence/History.cc
===================================================================
--- /fact/Evidence/History.cc	(revision 12939)
+++ /fact/Evidence/History.cc	(revision 12940)
@@ -52,4 +52,5 @@
 	
 	DimInfo *ServerList;
+	DimService *Service;
 	char *Directory;
 
@@ -72,5 +73,4 @@
 							 EvidenceServer(SERVER_NAME),
 							 Directory(Dir) {
-
   // Get/initialize configuration
   GetConfig("minchange", " ");
@@ -80,4 +80,7 @@
   GetConfig("exclude", "");
 
+  // Create services for information about subscribed services
+  Service = new DimService(SERVER_NAME "/Subscriptions", "C", NULL, 0);
+
   // Subscribe to top-level server list
   ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
@@ -90,4 +93,6 @@
   delete ServerList;
   while (Map.size() != 0) RemoveService((*Map.begin()).first);
+  
+  delete Service;
 }
 
@@ -96,9 +101,11 @@
 void History::infoHandler() {
 
+  static string List;
+
   DimInfo *I = getInfo();
 
   // Check if service available
   if (!ServiceOK(I)) return;
-  
+
   // ====== Part A: Handle service subscriptions ===
   
@@ -138,4 +145,14 @@
 	  Name = strtok(NULL, "|");
 	}
+	
+	// Update service subscription list
+	static stringstream Stream;
+	
+	for (map<string, struct Item>::const_iterator i=Map.begin(); i!=Map.end(); i++) {
+	  Stream << i->first << ':' << i->second.MinAbsChange << '|';
+	}
+	List = Stream.str();
+	Service->updateService((void *) List.c_str(), List.size()+1);
+	
 	return;
   }
Index: /fact/Evidence/readme.txt
===================================================================
--- /fact/Evidence/readme.txt	(revision 12939)
+++ /fact/Evidence/readme.txt	(revision 12940)
@@ -61,3 +61,6 @@
 			value of indices a to b)
 20/2/2012	Disabled padding per default in Evidence class constructor, and also in History and DColl
-			servers. EvidenceServer::ToString() can because of this now handle all format strings. 
+			servers. EvidenceServer::ToString() can because of this now handle all format strings.
+24/2/2012   Improved interactive behaviour of legend items (drag&drop, context menu). Handling of histories in
+			Edd much faster now. Made a new version Edd:LP for La Palma. History server publishes a list of
+			services subscribed to.
Index: /fact/tools/Edd/Edd.cc
===================================================================
--- /fact/tools/Edd/Edd.cc	(revision 12939)
+++ /fact/tools/Edd/Edd.cc	(revision 12940)
@@ -65,5 +65,10 @@
 
   SetActive(false);
-  while (!List.isEmpty()) DeleteCurve(List.last().Signal);
+
+  for (int i=0; i<List.size(); i++) {
+	DeleteCurve(List[i].Curve);
+	delete List[i].Trigger;
+  }
+
   delete RD;
   if (Tmpfile != NULL) fclose(Tmpfile);
@@ -75,16 +80,16 @@
   struct ItemDetails N;
   
-  N.Signal = NewCurve(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel)+ " (" + ToPixel(0, Board, Chip, Channel) + ")");
+  N.Curve = NewCurve(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel)+ " (" + ToPixel(0, Board, Chip, Channel) + ")");
   N.Board = Board;
   N.Chip = Chip;
   N.Channel = Channel;
   N.Trigger = new QwtPlotMarker();
-  N.Trigger->setSymbol(QwtSymbol(QwtSymbol::Diamond, QBrush(N.Signal->pen().color()), N.Signal->pen(), QSize(10,10)));
+  N.Trigger->setSymbol(QwtSymbol(QwtSymbol::Diamond, QBrush(N.Curve->pen().color()), N.Curve->pen(), QSize(10,10)));
   N.Trigger->attach(this);
 
   if (List.isEmpty()) {
-    QPen Pen = N.Signal->pen();
+    QPen Pen = N.Curve->pen();
 	Pen.setWidth(2);
-	N.Signal->setPen(Pen);
+	N.Curve->setPen(Pen);
   }
   List.append(N);
@@ -101,5 +106,5 @@
   ClearCurve(0);
 
-  List.first().Signal->setTitle(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel) + " (" + ToPixel(0, Board, Chip, Channel) + ")");
+  List.first().Curve->setTitle(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel) + " (" + ToPixel(0, Board, Chip, Channel) + ")");
   List.first().Board = Board;
   List.first().Chip = Chip;
@@ -239,8 +244,8 @@
   for (int i=0; i<List.size(); i++) {
 
-	if (PersistanceAction->isChecked()) List[i].Signal->setStyle(QwtPlotCurve::Dots);
+	if (PersistanceAction->isChecked()) List[i].Curve->setStyle(QwtPlotCurve::Dots);
 	else {
 	  ClearCurve(i);
-	  List[i].Signal->setStyle(QwtPlotCurve::Lines);
+	  List[i].Curve->setStyle(QwtPlotCurve::Lines);
 	}
 
@@ -298,13 +303,4 @@
   
   emit(PixelData(Pixel));
-}
-
-// Remove list entry
-void EventScope::DeleteCurve(QwtPlotCurve *Curve) {
-
-  for (int i=0; i<List.size(); i++) if (List[i].Signal == Curve) {
-	delete List[i].Trigger;
-    List.removeAt(i);
-  }
 }
 
Index: /fact/tools/Edd/Edd.h
===================================================================
--- /fact/tools/Edd/Edd.h	(revision 12939)
+++ /fact/tools/Edd/Edd.h	(revision 12940)
@@ -17,5 +17,5 @@
     struct ItemDetails {
 	  unsigned int Board, Chip, Channel;
-      QwtPlotCurve *Signal;
+      QwtPlotCurve *Curve;
 	  QwtPlotMarker *Trigger;
     };
@@ -45,5 +45,4 @@
   private slots:
 	void PlotTraces();
-	void DeleteCurve(QwtPlotCurve *);
 	void NewEventNum(int);
 
Index: /fact/tools/Edd_LP/Edd.cc
===================================================================
--- /fact/tools/Edd_LP/Edd.cc	(revision 12940)
+++ /fact/tools/Edd_LP/Edd.cc	(revision 12940)
@@ -0,0 +1,1099 @@
+/* ============================================================ 
+
+Edd - Evidence Data Display
+
+Qt-based graphical user interface for the Evidence contron system
+
+EddLineDisplay changes its background colour in case it display
+a DIM status service
+
+Note: Currently no limit to number of points in plot, can result in out of memory condition.
+
+============================================================ */
+
+#include "Edd.h"
+
+QString DRSBoard = "FADctrl";
+std::string PixelMapText;
+
+extern class EddDim *Handler;
+
+////////////////////////
+// Event oscilloscope //
+////////////////////////
+
+// Constructor
+EventScope::EventScope(class TP_DAQ *Page, QWidget *P): EddBasePlot(P), PixelMap(PixelMapText, false) {
+
+  // Initalise
+  LastPath = ".";
+  Name = DRSBoard+"/EventData";
+  DAQPage = Page;
+  Active = false;
+
+  // Open temporary files
+  Tmpfile = tmpfile();
+  if(Tmpfile==NULL || !File.open()) {
+    QMessageBox::warning(this, "Edd Message", "Could not open temporary file.", QMessageBox::Ok);
+	return;
+  }
+
+  // Open file with RawDataCTX
+  RD = new RawDataCTX(true);
+  ErrCode = CTX_NOTOPEN;
+
+  // Context menu
+  PhysPipeAction = new QAction("Physical pipeline", this);
+  PhysPipeAction->setCheckable(true);
+  connect(PhysPipeAction, SIGNAL(triggered()), SLOT(PlotTraces()));
+  Menu->insertAction(StripAction, PhysPipeAction);
+
+  PersistanceAction = new QAction("Persistance", this);
+  PersistanceAction->setCheckable(true);
+  Menu->insertAction(StripAction, PersistanceAction);
+  Menu->removeAction(StripAction);
+
+  // Initial trace
+  AddTrace(0,0,0);
+
+  // Update interval
+  Timer->setInterval(100);
+}
+
+// Destructor (items with parent widget are automatically deleted)
+EventScope::~EventScope() {
+
+  SetActive(false);
+
+  for (int i=0; i<List.size(); i++) {
+	DeleteCurve(List[i].Curve);
+	delete List[i].Trigger;
+  }
+
+  delete RD;
+  if (Tmpfile != NULL) fclose(Tmpfile);
+}  
+
+// Add trace
+void EventScope::AddTrace(int Board, int Chip, int Channel) {
+
+  struct ItemDetails N;
+  
+  N.Curve = NewCurve(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel)+ " (" + ToPixel(0, Board, Chip, Channel) + ")");
+  N.Board = Board;
+  N.Chip = Chip;
+  N.Channel = Channel;
+  N.Trigger = new QwtPlotMarker();
+  N.Trigger->setSymbol(QwtSymbol(QwtSymbol::Diamond, QBrush(N.Curve->pen().color()), N.Curve->pen(), QSize(10,10)));
+  N.Trigger->attach(this);
+
+  if (List.isEmpty()) {
+    QPen Pen = N.Curve->pen();
+	Pen.setWidth(2);
+	N.Curve->setPen(Pen);
+  }
+  List.append(N);
+    
+  PlotTraces();
+}
+
+// Update last trace (to reflect current setting of spin boxes in DAQ page)
+void EventScope::UpdateFirst(int Board, int Chip, int Channel) {
+
+  if (List.isEmpty()) return;
+  
+  // Clear in case persistance was activated
+  ClearCurve(0);
+
+  List.first().Curve->setTitle(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel) + " (" + ToPixel(0, Board, Chip, Channel) + ")");
+  List.first().Board = Board;
+  List.first().Chip = Chip;
+  List.first().Channel = Channel;
+    
+  PlotTraces();
+}
+  
+// Update event buffer
+void EventScope::Update(const QString &, int Time, const QByteArray &Data, const QString &Format, const QString &, int) {
+
+  // Check if service available
+  if (!SetStatus(this, Name, Time, Format)) return;
+  if (Data.size() < (int) sizeof(RunHeader)) return;
+
+  // Ignore further data while processing this one
+  Handler->Ignore(Name, true);
+  
+  // Clear temporary file and write event data to this file
+  File.resize(0);
+  if (File.write(Data) == -1) {
+	QMessageBox::warning(this, "Edd Message","Could not write data to temporary file.",QMessageBox::Ok);
+	return;	
+  }
+  File.flush();
+
+  // Open temporary raw data file
+  OpenRawFile(File.fileName());
+
+  // Process all pending events, then allow data again
+  QApplication::processEvents();
+  Handler->Ignore(Name, false);
+}
+
+
+// New event number selected in raw data browser
+void EventScope::OpenRawFile(QString Filename) {
+
+  // Request filename to open if none given
+  if (Filename.isEmpty()) {
+    Filename = QFileDialog::getOpenFileName(this, "Open raw file", LastPath, "Raw data files (*.raw);; All files (*)");
+    if (Filename == NULL) return;
+  }
+
+  DAQPage->FilenameBox->setText(Filename);
+  LastPath = QFileInfo(Filename).absolutePath();
+  
+  // Prepare temporary file for run header
+  if (ftruncate(fileno(Tmpfile), 0) == -1) printf("Error with ftruncate() in EventScope::OpenRawFile() (%s)\n", strerror(errno));  
+  rewind(Tmpfile);
+
+  // Write run header to temporary file  
+  switch (ErrCode = RD->OpenDataFile(Filename.toAscii().data(), Tmpfile)) {
+    case CTX_FOPEN:   QMessageBox::warning(this, "Edd Message","Could not open file.",QMessageBox::Ok);
+                      return;
+    case CTX_RHEADER: QMessageBox::warning(this, "Edd Message","Could not read run header.",QMessageBox::Ok);
+					  return;
+    case CTX_BSTRUCT: QMessageBox::warning(this, "Edd Message","Could not read board structures.",QMessageBox::Ok);
+					  return;
+    default:		  break;
+  }
+  RunHeader *R = RD->RHeader;
+
+  // Magic number warnings not for online display
+  if (Filename != File.fileName()) {
+    if (R->MagicNum == MAGICNUM_OPEN) {
+      QMessageBox::warning(this, "Edd Message","Magic number in run header indicates that the file has not been closed properly.",QMessageBox::Ok);
+    }
+    if (R->MagicNum == MAGICNUM_ERROR) {
+      QMessageBox::warning(this, "Edd Message","Magic number in run header indicates that an error occurred while writing the file.",QMessageBox::Ok);
+    }
+  }
+
+  // Print run header to display
+  rewind(Tmpfile);
+  QTextStream in(Tmpfile);
+  QString text = in.readAll();
+  DAQPage->RunHeaderDisplay->setPlainText(text);
+
+  // Read and display first event (must be before setting spin boxes)
+  NewEventNum(DAQPage->Event->value());
+
+  // Update spin box ranges on DAQ page  
+  DAQPage->Event->setRange(0, R->Events-1);
+  DAQPage->Event->setEnabled(true);
+  DAQPage->Channel->setRange(0, R->NChannels-1);
+  DAQPage->Chip->setRange(0, R->NChips-1);
+  DAQPage->Board->setRange(0, R->NBoards-1); 
+}
+
+// New event number selected in raw data browser
+void EventScope::NewEventNum(int Event) {
+
+  // Prepare temporary file for event header  
+  if (ftruncate(fileno(Tmpfile), 0) == -1) printf("Error with ftruncate() in EventScope::NewEventNum() (%s)\n", strerror(errno));
+  rewind(Tmpfile);
+
+  // Read event
+  if (RD->ReadEvent(Event, Tmpfile) != CTX_OK) {
+    QMessageBox::warning(this, "Edd Message","Could not read event.",QMessageBox::Ok);
+    DAQPage->EventHeaderDisplay->clear();
+    return;
+  }
+
+  // Plot traces for event
+  PlotTraces();
+}
+
+// Update curves
+void EventScope::PlotTraces() {
+
+  double x,y;
+  unsigned int Cell, Trig;
+  static int Last = 0;
+
+  // Only process if valid data in RawDataCTX class
+  if (ErrCode != CTX_OK) return;
+
+  // Print event header and trigger cell information from event data
+  rewind(Tmpfile);
+  QTextStream in(Tmpfile);
+  QString text = in.readAll();
+  
+  text.append("\nTrigger cells: ");
+  for (unsigned int i=0; i<RD->RHeader->NBoards*RD->RHeader->NChips; i++) {
+    QString a;
+    text.append(a.sprintf("%d ", *((int *)RD->Data + i)));
+  }
+  DAQPage->EventHeaderDisplay->setPlainText(text);
+  
+  // Set x axis title
+  if (PhysPipeAction->isChecked()) setAxisTitle(QwtPlot::xBottom, "Time from start of pipeline (ns)");
+  else setAxisTitle(QwtPlot::xBottom, "Time from trigger minus one revolution (ns)");
+
+  // Loop through event data to update event scope
+  RunHeader *R = RD->RHeader;
+  for (int i=0; i<List.size(); i++) {
+
+	if (PersistanceAction->isChecked()) List[i].Curve->setStyle(QwtPlotCurve::Dots);
+	else {
+	  ClearCurve(i);
+	  List[i].Curve->setStyle(QwtPlotCurve::Lines);
+	}
+
+ 	// Check if current event contains requested trace
+    if (List[i].Board>=R->NBoards || List[i].Chip>=R->NChips || List[i].Channel>=R->NChannels) continue;
+
+	// Set trigger marker visibility
+	List[i].Trigger->setVisible(PhysPipeAction->isChecked());
+	
+	// Determine trigger cell
+	Trig = *((int *) RD->Data + List[i].Board*R->NChips + List[i].Chip);
+
+	// Calulate point of curve
+	for (unsigned int j=0; j<R->Samples; j++) {
+
+	  if (PhysPipeAction->isChecked()) Cell = (j - Trig) % 1024;
+	  else Cell = j;
+
+	  x = j / RD->BStruct[List[i].Board].NomFreq;
+	  y = *((short *) (RD->Data + R->NBoards*R->NChips*sizeof(int)) +
+	  	List[i].Board*R->NChips*R->NChannels*R->Samples + List[i].Chip*R->NChannels*R->Samples +
+		List[i].Channel*R->Samples + Cell) * RD->BStruct[List[i].Board].ScaleFactor;
+
+	  AddPoint(i, x, y);
+	  
+	  // Set trigger point indicator
+	  if (Trig == j) List[i].Trigger->setValue(x, y);	
+    }
+  }
+
+  // Limit update rate in persistance mode 
+  if (!PersistanceAction->isChecked() || time(NULL) > Last) {
+    UpdatePlot();
+    Last = time(NULL);
+  }
+
+  // Loop through event data for pixel display
+  QVector<double> Pixel(R->NBoards*R->NChips*R->NChannels);
+  int Count = 0;
+
+  for (unsigned int Board=0; Board<R->NBoards; Board++) {
+  for (unsigned int Chip=0; Chip<R->NChips; Chip++) {
+  for (unsigned int Channel=0; Channel<R->NChannels; Channel++) {
+    Pixel[Count] = DBL_MIN;
+
+	for (unsigned int i=0; i<R->Samples; i++) {
+	  y = *((short *) (RD->Data + R->NBoards*R->NChips*sizeof(int)) +
+		Board*R->NChips*R->NChannels*R->Samples + Chip*R->NChannels*R->Samples +
+		Channel*R->Samples + i) * RD->BStruct[Board].ScaleFactor;
+
+	  if (y > Pixel[Count]) Pixel[Count] = y;
+    }
+	Count++;	  
+  }}}
+  
+  emit(PixelData(Pixel));
+}
+
+// Set display active (if inactive, disconnect from server)
+void EventScope::SetActive(bool State) {
+
+  if (State && !Active) Handler->Subscribe(DRSBoard+"/EventData", this, -1);
+  if (!State && Active) Handler->Unsubscribe(DRSBoard+"/EventData", this);
+
+  Active = State;
+}
+
+// Translate FPA ID to Pixel ID (use '-' instead of PM_ERROR_CODE)
+QString EventScope::ToPixel(unsigned int Crate, unsigned int Board, unsigned int Patch, unsigned int Pixel) {
+  
+  if (FPA_to_Pixel(Crate, Board, Patch, Pixel) == PM_ERROR_CODE) return "-";
+  else return QString::number(FPA_to_Pixel(Crate, Board, Patch, Pixel));
+}
+  
+//------------------------------------------------------------------
+//**************************** Tab pages ***************************
+//------------------------------------------------------------------
+
+//
+// Environment page (For M0, server was called ARDUINO)
+//
+TP_Environment::TP_Environment() {
+
+  QGridLayout *Layout = new QGridLayout(this);
+  setAttribute(Qt::WA_DeleteOnClose);
+
+  // Status display
+  EddLineDisplay *Line = new EddLineDisplay("FSC_CONTROL/MESSAGE");
+  Line->setMaximumWidth(300);
+  Layout->addWidget(Line, 0, 0, 1, 4);      
+
+  Line = new EddLineDisplay("FSCctrl/Time");
+  Layout->addWidget(Line, 0, 5, 1, 2);      
+
+  // Temperatures
+  EddPlot *Plot = new EddPlot();
+  for (int i=1; i<59; i++) {
+    Line = new EddLineDisplay("FSC_CONTROL/TEMPERATURE", i);
+    Line->setMaximumWidth(50);
+    Layout->addWidget(Line, i/8+1, i%8);
+    Plot->AddService("FSC_CONTROL/TEMPERATURE", i);
+  }
+  Layout->addWidget(Plot, 0, 10, 22, 15);      
+
+  // Voltages and currents
+  for (int i=0; i<40; i++) {
+    Line = new EddLineDisplay("FSC_CONTROL/VOLTAGE", i);
+    Line->setMaximumWidth(50);
+    Layout->addWidget(Line, i/8+10, i%8);
+
+    Line = new EddLineDisplay("FSC_CONTROL/CURRENT", i);
+    Line->setMaximumWidth(50);
+    Layout->addWidget(Line, i/8+16, i%8);
+  }
+
+  // Night sky monitor
+  Line = new EddLineDisplay("SQM/Message");
+  Line->setMaximumWidth(300);
+  Layout->addWidget(Line, 22, 0, 1, 4);      
+
+  Line = new EddLineDisplay("SQM/NSB");
+  Layout->addWidget(Line, 22, 5, 1, 2);          
+}
+
+//
+// Bias page
+//
+TP_Bias::TP_Bias() {
+
+  QGridLayout *Layout = new QGridLayout(this);
+  setAttribute(Qt::WA_DeleteOnClose);
+  EddLineDisplay *Line;
+
+  Line = new EddLineDisplay("BIAS_CONTROL/MESSAGE");
+  Line->setMaximumWidth(400);
+  Layout->addWidget(Line, 0, 0, 1, 11);      
+
+  EddPlot *Plot = new EddPlot();
+  for (int i=0; i<320; i++) Plot->AddService("BIAS_CONTROL/VOLTAGE", i);	
+  Layout->addWidget(Plot, 1, 0, 30, 12);
+
+  // Current page
+  EddWindow *Button = new EddWindow("Currents", "Edd - Bias currents");
+  Layout->addWidget(Button, 0, 11);      
+
+  Plot = new EddPlot();
+  for (int i=0; i<320; i++) Plot->AddService("BIAS_CONTROL/CURRENT", i);	
+  Button->Layout()->addWidget(Plot, 0, 4, 30, 12);
+}
+
+//
+// Feedback page
+//
+TP_Feedback::TP_Feedback() {
+
+  setAttribute(Qt::WA_DeleteOnClose);
+  QGridLayout *Layout = new QGridLayout(this);
+  EddLineDisplay *Line;
+
+  EddPlot *Plot = new EddPlot();
+  for (int i=0; i<36; i++) {
+    Line = new EddLineDisplay("Feedback/Average", i);
+	Line->setMaximumWidth(60);
+    Layout->addWidget(Line, i%9+2, 0+i/9, 1, 1);
+    Plot->AddService("Feedback/Average", i);
+  }
+  Layout->addWidget(Plot, 0, 4, 12, 10);
+
+  Line = new EddLineDisplay("Feedback/Message");
+  Line->setMaximumWidth(200);
+  Layout->addWidget(Line, 0, 0, 1, 2);      
+
+  Line = new EddLineDisplay("Feedback/State");
+  Line->setMaximumWidth(150);
+  Layout->addWidget(Line, 1, 0, 1, 2);      
+  Line = new EddLineDisplay("Feedback/Count");
+  Line->setMaximumWidth(60);
+  Layout->addWidget(Line, 1, 2);      
+
+  // Details page
+  EddWindow *Button = new EddWindow("Details", "Edd - Feedback Details");
+  Layout->addWidget(Button, 12, 0, 1, 1);      
+
+  Plot = new EddPlot();
+
+  for (int i=0; i<36; i++) {
+    Line = new EddLineDisplay("Feedback/Sigma", i);
+	Line->setMaximumWidth(60);
+    Button->Layout()->addWidget(Line, i%9, 0+i/9, 1, 1);
+    Plot->AddService("Feedback/Sigma", i);
+	
+    Line = new EddLineDisplay("Feedback/Target", i);
+	Line->setMaximumWidth(60);
+    Button->Layout()->addWidget(Line, i%9+10, 0+i/9, 1, 1);
+	
+	Line = new EddLineDisplay("Feedback/Response", i);
+	Line->setMaximumWidth(60);
+    Button->Layout()->addWidget(Line, i%9+20, 0+i/9, 1, 1);
+  }
+  Button->Layout()->addWidget(Plot, 0, 4, 30, 12);
+}
+
+
+//
+// FADctrl page
+//
+TP_FADctrl::TP_FADctrl() {
+
+  QString Board;
+
+  QScrollArea *scrollArea = new QScrollArea;
+  scrollArea->setBackgroundRole(QPalette::Dark);
+  scrollArea->setWidget(this);
+  setMinimumSize(QSize(0,0)); 
+  
+  QGridLayout *Layout = new QGridLayout(this);
+  setAttribute(Qt::WA_DeleteOnClose);
+  EddLineDisplay *Line;
+
+  Line = new EddLineDisplay("FAD_CONTROL/MESSAGE");
+  Line->setMaximumWidth(500);
+  Layout->addWidget(Line, 0, 0, 1, 10);      
+
+  EddPlot *Plot = new EddPlot();
+  Layout->addWidget(Plot, 1, 0, 6, 10);
+  for (int i=0; i<82; i++) Plot->AddService("FAD_CONTROL/TEMPERATURE", i);
+
+  // Details page
+  EddWindow *Button[2];
+  Button[0] = new EddWindow("Boards 0-19", "Edd - FADctrl - Board 0 to 19");
+  Button[1] = new EddWindow("Boards 20-39", "Edd - FADctrl - Board 20 to 39");
+  Layout->addWidget(Button[0], 7, 0, 1, 1);      
+  Layout->addWidget(Button[1], 7, 1, 1, 1);      
+
+  for (int i=0; i<40; i++) {
+    Board = Board.sprintf("FADctrl/Board%.2d/", i);
+    Line = new EddLineDisplay(Board+"Server");
+	Line->setMinimumWidth(90);
+    Button[i/20]->Layout()->addWidget(Line, i+7, 0, 1, 1);
+
+    Line = new EddLineDisplay(Board+"BoardID");
+	Line->setMaximumWidth(30);
+    Button[i/20]->Layout()->addWidget(Line, i+7, 1, 1, 1);
+
+    Line = new EddLineDisplay(Board+"Frequency");
+	Line->setMaximumWidth(40);
+    Button[i/20]->Layout()->addWidget(Line, i+7, 2, 1, 1);
+
+	for (int j=0; j<4; j++) {
+      Line = new EddLineDisplay(Board+"Lock", j);
+	  Line->setMaximumWidth(20);
+      Button[i/20]->Layout()->addWidget(Line, i+7, 3+j, 1, 1);
+	}
+
+	for (int j=0; j<4; j++) {
+      Line = new EddLineDisplay(Board+"Temperature", j);
+	  Line->setMinimumWidth(40);
+      Button[i/20]->Layout()->addWidget(Line, i+7, 7+j, 1, 1);
+	}
+
+    Line = new EddLineDisplay(Board+"TriggerNum");
+	Line->setMinimumWidth(40);
+    Button[i/20]->Layout()->addWidget(Line, i+7, 11, 1, 1);
+
+	Line = new EddLineDisplay(Board+"RateHz");
+	Line->setMinimumWidth(50);
+    Button[i/20]->Layout()->addWidget(Line, i+7, 19, 1, 1);
+
+	Line = new EddLineDisplay(Board+"Status");
+	Line->setMaximumWidth(150);
+    Button[i/20]->Layout()->addWidget(Line, i+7, 20, 1, 1);
+  }
+}
+
+//
+// Event scope page
+//
+TP_DAQ::TP_DAQ(bool IsBrowser) {
+
+  EddLineDisplay *Line;
+
+  setAttribute(Qt::WA_DeleteOnClose);
+  QGridLayout *Layout = new QGridLayout(this);
+
+  // Event scope
+  Scope = new EventScope(this);
+  Scope->setMinimumWidth(700);
+
+  Scope->SetActive(!IsBrowser);
+
+  // FilenameBox must exist also for online browser (but not added to layout)
+  FilenameBox = new QLineEdit();
+
+  if (!IsBrowser) {
+	// Message service
+	Line = new EddLineDisplay(DRSBoard+"/Message");
+	Line->setMinimumWidth(500);
+	Layout->addWidget(Line, 0, 1, 1, 6);      
+
+	// Run-related information 
+	Line = new EddLineDisplay(DRSBoard+"/EventNumber");
+	Line->setMaximumWidth(100);
+	Layout->addWidget(Line, 0, 8, 1, 1);      
+	Line = new EddLineDisplay(DRSBoard+"/FileSizeMB");
+	Line->setMaximumWidth(100);
+	Layout->addWidget(Line, 0, 9, 1, 1);      
+  }
+  else {
+  	// Filename box
+	Layout->addWidget(FilenameBox, 0, 1, 1, 6);      
+	connect(FilenameBox, SIGNAL(returnPressed()), SLOT(OpenDataFile()));
+	FilenameBox->setToolTip("Raw data file name");
+
+    // Browse botton
+	QToolButton *LoadButton = new QToolButton();
+	LoadButton->setToolButtonStyle (Qt::ToolButtonTextOnly);
+	LoadButton->setText("...");
+	Layout->addWidget(LoadButton, 0, 7, 1, 1);      
+	connect(LoadButton, SIGNAL(clicked()), Scope, SLOT(OpenRawFile()));
+	LoadButton->setToolTip("Open file dialog to select raw data file");
+  }
+
+  // Text boxes for run and event header
+  RunHeaderDisplay = new QPlainTextEdit();
+  EventHeaderDisplay = new QPlainTextEdit();
+  RunHeaderDisplay->setReadOnly(true);
+  EventHeaderDisplay->setReadOnly(true);
+
+  // Tab widget
+  QTabWidget *TabWidget = new QTabWidget();
+  TabWidget->addTab(Scope, "&Signals");
+  TabWidget->addTab(RunHeaderDisplay, "&Run Header");
+  TabWidget->addTab(EventHeaderDisplay, "&Event Header");
+  Layout->addWidget(TabWidget, 1, 1, 7, 12);
+
+  // Channel number 
+  Channel = new QSpinBox;
+  connect(Channel, SIGNAL(valueChanged(int)), SLOT(UpdateScope(int)));
+  Channel->setToolTip("Channel number");
+
+  // Chip number 
+  Chip = new QSpinBox;
+  connect(Chip, SIGNAL(valueChanged(int)), SLOT(UpdateScope(int)));
+  Chip->setToolTip("Chip number");
+
+  // Board number 
+  Board = new QSpinBox;
+  connect(Board, SIGNAL(valueChanged(int)), SLOT(UpdateScope(int)));
+  Board->setToolTip("Board number");
+
+  // Pixel ID
+  PixelID = new QSpinBox;
+  PixelID->setMaximumWidth(60);
+  PixelID->setRange(-1, 9999);
+  PixelID->setSpecialValueText("n/a");
+  connect(PixelID, SIGNAL(valueChanged(int)), SLOT(TranslatePixelID(int)));
+  PixelID->setToolTip("Pixel identification");
+
+  // Add trace permanently
+  QPushButton *Button = new QPushButton("Keep trace");
+  Button->setToolTip("Keep trace in display");
+  Button->setMaximumWidth(80);
+  connect(Button, SIGNAL(clicked()), SLOT(KeepCurrent()));
+  
+  // Layout of pixel addressing widgets
+  QFormLayout *FormLayout = new QFormLayout();
+  FormLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
+  FormLayout->addRow("Board", Board);
+  FormLayout->addRow("Chip", Chip);
+  FormLayout->addRow("Channel", Channel);
+  FormLayout->addRow("Pixel ID", PixelID);
+  FormLayout->addRow("", Button);
+  Layout->addLayout(FormLayout, 0, 0, 4, 1);
+
+  // Spin box for event number 
+  Event = new QSpinBox;
+  Event->setToolTip("Event number");
+  Event->setEnabled (false);
+  
+  // Stop/start button
+  StartStopButton = new QPushButton("Stop");
+  StartStopButton->setToolTip("Start/stop display");
+  StartStopButton->setMaximumWidth(80);
+  StartStopButton->setCheckable(true);
+  QPalette Palette = StartStopButton->palette();
+  Palette.setColor(QPalette::ButtonText, Qt::blue);
+  Palette.setColor(QPalette::Button, Qt::green);
+  StartStopButton->setPalette(Palette);
+  StartStopButton->setFont(QFont("Times", 10, QFont::Bold));
+
+  if (IsBrowser) {
+	FormLayout = new QFormLayout();
+	FormLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
+	FormLayout->addRow("Event Num", Event);
+	Layout->addLayout(FormLayout, 6, 0);
+	connect(Event, SIGNAL(valueChanged(int)), Scope, SLOT(NewEventNum(int)));
+  }
+  else {
+	Layout->addWidget(StartStopButton, 6, 0);
+	connect(StartStopButton, SIGNAL(toggled(bool)), SLOT(StartStop(bool)));
+  }
+  
+  // Event display page
+  EddWindow *New = new EddWindow("Pixel display", "Edd - Event display");
+  New->setFont(QFont("Times", 10, QFont::Bold));
+  New->setMaximumWidth(80);
+  New->setToolTip("Show event display window");
+  Layout->addWidget(New, 7, 0);      
+  
+  Pixel = new QPushButton *[MAXPIXEL];
+  int Count = 0;
+  double x,y;
+  
+  for (int ix=-22; ix<=22; ix++) for (int iy=-19; iy<=20; iy++) {  
+    if (Count == MAXPIXEL) break;
+	
+	x = ix*0.866;
+	y = iy - (ix%2==0 ? 0.5:0);
+    if ((pow(x,2)+pow(y,2) >= 395) && !(abs(ix)==22 && iy==7)) continue;
+	
+    //Pixel[Count] = new QPushButton(Display);
+    Pixel[Count] = new QPushButton(New->Window());
+	Pixel[Count]->setAutoFillBackground(true);
+	Pixel[Count]->setGeometry((int) (x*12.5 + 250), (int) (y*12.5 + 250), 10, 10);
+	Pixel[Count]->show();
+	Count++;
+  }
+
+  // Connect slots for updating displays
+  if (!IsBrowser) StartStop(false);
+  connect(Scope, SIGNAL(PixelData(QVector<double>)), SLOT(SetPixelData(QVector<double>)));
+
+  // Call to get initial pixel ID correct
+  UpdateScope(0);
+}
+
+TP_DAQ::~TP_DAQ() {
+
+  delete[] Pixel;
+}
+
+// Translate pixel ID to board, chip, channel
+void TP_DAQ::TranslatePixelID(int ID) {
+
+  // setValue() below will call UpdateScope() through signal, therefore need to store numbers here
+  unsigned int BoardNo = Scope->Pixel_to_FPAboard(ID);
+  unsigned int PatchNo = Scope->Pixel_to_FPApatch(ID);
+  unsigned int PixelNo = Scope->Pixel_to_FPApixel(ID);
+  
+  if (BoardNo == Scope->PM_ERROR_CODE) PixelID->setValue(-1);
+  else {
+    Board->setValue(BoardNo);
+    Chip->setValue(PatchNo);
+    Channel->setValue(PixelNo);
+  }
+}
+
+// Keep current trace
+void TP_DAQ::KeepCurrent() {
+
+  Scope->AddTrace(Board->value(), Chip->value(), Channel->value());
+}
+
+// Start/stop event acquisition
+void TP_DAQ::StartStop(bool State) {
+
+  Scope->SetActive(!State);
+  StartStopButton->setText(State ? "Start" : "Stop");
+}
+
+// Open raw data file
+void TP_DAQ::OpenDataFile() {
+
+  Scope->OpenRawFile(FilenameBox->text());
+}
+
+// Update event scope
+void TP_DAQ::UpdateScope(int) {
+
+  // Update pixel ID
+  PixelID->setValue(Scope->FPA_to_Pixel(0, Board->value(), Chip->value(), Channel->value()));
+  if (PixelID->value() == (int) Scope->PM_ERROR_CODE) PixelID->setValue(-1);
+  
+  // Update first trace
+  Scope->UpdateFirst(Board->value(), Chip->value(), Channel->value());
+}
+
+// Show/hide pixel display
+void TP_DAQ::ShowPixelDisplay() {
+
+  Display->show();
+  Display->raise();
+}
+
+void TP_DAQ::SetPixelData(QVector<double> Data) {
+
+  QwtLinearColorMap Map;
+
+  for (int i=0; i<Data.size(); i++) {
+	Pixel[i]->setPalette(QPalette(Map.color(QwtDoubleInterval(300, 400), Data[i])));
+  }
+}
+
+
+//
+// Evidence page
+//
+TP_Evidence::TP_Evidence() {
+
+  setAttribute(Qt::WA_DeleteOnClose);
+  QGridLayout *Layout = new QGridLayout(this);
+  EddLineDisplay *Line;
+  EddText *Text;
+  
+  Line = new EddLineDisplay("Alarm/Message");
+  Line->setMaximumWidth(200);
+  Layout->addWidget(Line, 0, 0, 1, 2);      
+
+  QPushButton *Button = new QPushButton();
+  Button->setText("ON/OFF");
+  Button->setCheckable(true);
+  connect(Button, SIGNAL(toggled(bool)), SLOT(ToggleAlarm(bool)));
+  Layout->addWidget(Button, 0, 3, 1, 1);
+
+  Line = new EddLineDisplay("Alarm/MasterAlarm");
+  Layout->addWidget(Line, 0, 1, 1, 1);
+
+  Text = new EddText("Alarm/Summary", true);
+  Text->Accumulate = false;
+  Text->setMaximumWidth(200);
+  Text->setMaximumHeight(150);
+  Layout->addWidget(Text, 1, 0, 1, 2);
+
+  Line = new EddLineDisplay("DColl/Message");
+  Line->setMaximumWidth(200);
+  Layout->addWidget(Line, 3, 0, 1, 2);      
+
+  Line = new EddLineDisplay("DColl/DataSizeMB");
+  Layout->addWidget(Line, 4, 0, 1, 1);
+
+  Line = new EddLineDisplay("DColl/LogSizeMB");
+  Layout->addWidget(Line, 4, 1, 1, 1);
+
+  Line = new EddLineDisplay("DColl/CurrentFile");
+  Line->setMaximumWidth(400);
+  Layout->addWidget(Line, 5, 0, 1, 3);
+
+  Line = new EddLineDisplay("Config/Message");
+  Line->setMaximumWidth(200);
+  Layout->addWidget(Line, 6, 0, 1, 2);      
+
+  Line = new EddLineDisplay("Config/ModifyTime");
+  Line->setMaximumWidth(200);
+  Line->ShowAsTime = true;
+  Layout->addWidget(Line, 7, 0, 1, 1);
+
+  Button = new QPushButton();
+  Button->setText("eLogBook");
+  connect(Button, SIGNAL(released()), SLOT(StartELog()));
+  Layout->addWidget(Button, 6, 1, 1, 1);
+
+  Button = new QPushButton();
+  Button->setText("DIM browser");
+  connect(Button, SIGNAL(released()), SLOT(StartDIMBrowser()));
+  Layout->addWidget(Button, 7, 1, 1, 1);
+
+  Line = new EddLineDisplay("Edd/Rate_kBSec");
+  Layout->addWidget(Line, 8, 0, 1, 1);
+}
+
+// Toggle state of Alarm server
+void TP_Evidence::ToggleAlarm(bool State) {
+
+  if (State) DimClient::sendCommandNB((char *) "Alarm/Switch", (char *) "off");
+  else DimClient::sendCommandNB((char *) "Alarm/Switch", (char *) "on");
+}
+ 
+// Start DIM Browser
+void TP_Evidence::StartDIMBrowser() {
+
+  QProcess::startDetached("did", QStringList(), QString(getenv("DIMDIR"))+"/linux/");
+}
+
+// Start eLogBook
+void TP_Evidence::StartELog() {
+
+  QProcess::startDetached("firefox http://fact.ethz.ch/FACTelog/index.jsp");
+}
+
+ 
+//--------------------------------------------------------------------
+//*************************** Main GUI *******************************
+//--------------------------------------------------------------------
+//
+// All widgets have ultimately Central as parent.
+//
+GUI::GUI() {
+
+  Handler = new EddDim;
+
+  // Arrangement in tabs
+  TabWidget = new QTabWidget(this);
+  TabWidget->setTabsClosable(true);
+  connect(TabWidget, SIGNAL(tabCloseRequested(int)), SLOT(DetachTab(int)));
+  TabWidget->addTab(new TP_DAQ(false), "Event scope");
+  printf("...event scope\n");
+  TabWidget->addTab(new TP_FADctrl, "FAD");
+  printf("...FADctrl\n");
+  TabWidget->addTab(new TP_Bias, "Bias");
+  printf("...bias\n");
+  //TabWidget->addTab(new TP_Feedback, "Feedback");
+  //printf("...feedback\n");
+  TabWidget->addTab(new TP_Environment, "FSC/SQM");
+  printf("...FSC\n");
+  TabWidget->addTab(new TP_Evidence, "Evidence");
+
+  // Set features of main window
+  setStatusBar(new QStatusBar(this));
+  setWindowTitle("Edd - Evidence Data Display - Node: " + QString(DimServer::getDnsNode()) + ":" + QString::number(DimServer::getDnsPort()));
+  setCentralWidget(TabWidget);
+
+  // Menu bar
+  QMenu* Menu = menuBar()->addMenu("&Menu");
+  Menu->addAction("Open history plot", this, SLOT(MenuNewHistory()));
+  Menu->addAction("Send command", this, SLOT(MenuCommand()));
+  Menu->addAction("Raw data browser", this, SLOT(MenuRawDataBrowser()));
+  Menu->addSeparator();
+  Menu->addAction("About", this, SLOT(MenuAbout()));
+  Menu->addSeparator();
+  QAction* QuitAction = Menu->addAction("Quit", qApp, SLOT(quit()));
+  QuitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
+
+  // Size and show main window
+  QSize Size = TabWidget->sizeHint()*1.1;
+  Size = Size.boundedTo(QApplication::desktop()->screenGeometry(this).size()*0.6);
+  //setMaximumSize(QApplication::desktop()->screenGeometry(this).size()*0.9);
+  TabWidget->resize(Size);
+  TabWidget->setMaximumSize(QApplication::desktop()->screenGeometry(this).size()*0.9);
+  show();
+
+  // Set timer to regularly check the master alarm
+  QTimer *Timer = new QTimer(this);
+  connect(Timer, SIGNAL(timeout()), this, SLOT(CheckAlarm()));
+  if (QString(DimServer::getDnsNode()).contains("ethz.ch")) Timer->start(5000);
+}  
+    
+
+void GUI::MenuAbout() {
+  QString Rev(SVN_REVISION);
+  Rev.remove(0,1).chop(2);
+  
+  QMessageBox::about(this, "About Edd","Evidence Data Display\n\n"
+    "Written by Oliver Grimm, IPP, ETH Zurich\n"
+    "This version compiled "__DATE__" ("+Rev+")\n\n"
+    "Graphical user interface implemented with Qt and Qwt.\n"
+    "Evidence control system based on DIM (http://dim.web.cern.ch).\n\n"
+    "Comments to oliver.grimm@phys.ethz.ch.");
+}
+
+// Open new history plot
+void GUI::MenuNewHistory() {
+
+  QStringList List, Index;
+  char *Name, *Format;
+  int Type;
+  bool OK;
+
+  // Find all DIM services and sort
+  getServices("*");
+  while ((Type = getNextService(Name, Format)) != 0) {
+    if (Type==DimSERVICE) List.append(Name);
+  }
+  List.sort();
+
+  // Open dialog and open history window
+  QString Result = QInputDialog::getItem(this, "Edd Request",
+    "Enter or choose DIM service name (add index or index range a-b separated by colon)", List, 0, true, &OK);
+
+  // Check if cancelled or empty data
+  List = Result.trimmed().split(":", QString::SkipEmptyParts);
+  if (!OK || List.isEmpty()) return;
+
+  // Check if index was given
+  if (List.size() == 1) {
+	OpenHistory(List[0].toAscii().data(), -1);
+	return;
+  }
+
+  // Single index or index range?
+  Index = List[1].trimmed().split("-", QString::SkipEmptyParts);
+  if (Index.isEmpty()) {
+  	QMessageBox::warning(NULL, "Edd Message", QString("Incorrect index range given") ,QMessageBox::Ok);
+	return;
+  }
+
+  if (Index.size() == 1) OpenHistory(List[0].toAscii().data(), atoi(Index[0].toAscii().data()));
+  else OpenHistory(List[0].toAscii().data(), atoi(Index[0].toAscii().data()), atoi(Index[1].toAscii().data()));
+}
+
+// Send command selected from list
+void GUI::MenuCommand() {
+
+  QStringList List;
+  char *Name, *Format;
+  int Type;
+  bool OK;
+
+  // Find all DIM commands and sort
+  getServices("*");
+  while ((Type = getNextService(Name, Format)) != 0) {
+    if (Type==DimCOMMAND) List.append(Name);
+  }
+  List.sort();
+
+  // Open dialog and open window for entering command
+  QString Result = QInputDialog::getItem(this, "Edd Request",
+    "Enter or choose DIM command name", List, 0, true, &OK);
+  if (OK && !Result.isEmpty()) {
+    Result = Result.trimmed();
+	
+	QMainWindow *M = new QMainWindow;
+	M->setCentralWidget(new QWidget(M));
+	M->setStatusBar(new QStatusBar(M));
+	M->setAttribute(Qt::WA_DeleteOnClose);
+	QWidget *W = new EddCommand(Result.toAscii().data());
+	QFormLayout *FormLayout = new QFormLayout(M->centralWidget());
+	FormLayout->setRowWrapPolicy(QFormLayout::WrapAllRows);
+	FormLayout->addRow("Enter argument for " + Result, W);
+	M->show();
+  }
+}
+
+// Raw data browser
+void GUI::MenuRawDataBrowser() {
+
+  DetachTab(0, true);
+}
+
+// Open tab as separate window
+void GUI::DetachTab(int Tab, bool IsDAQBrowser) {
+
+  QWidget *W = NULL;
+  QMainWindow *M = new QMainWindow;
+
+  M->setCentralWidget(new QWidget(M));
+  M->setStatusBar(new QStatusBar(M));
+
+  switch(Tab) {
+	case 0:	W = new TP_DAQ(IsDAQBrowser); break;
+	case 1:	W = new TP_FADctrl; break;
+	case 2: W = new TP_Bias; break;
+	case 3: W = new TP_Feedback; break;
+	case 4: W = new TP_Environment; break;
+	case 5: W = new TP_Evidence; break;
+	default: break;
+  }
+
+  if (W == NULL) {
+    delete M->centralWidget();
+	delete M;
+	return;
+  }
+
+  W->setParent(M);
+  W->resize(size());
+  M->resize(size());
+  if (!IsDAQBrowser) M->setWindowTitle("Edd - " + TabWidget->tabText(Tab));
+  else M->setWindowTitle("Edd - Raw Data Browser");
+  M->show();
+  
+  return;
+}
+
+// Check alarm level and if Alarm server is alive
+void GUI::CheckAlarm() {
+
+  static int WarnedLevel = 0;
+  static bool AlarmServerWarned = false;
+
+  // === Check service Alarm/MasterAlarm ===
+  DimCurrentInfo MasterAlarm("Alarm/MasterAlarm", -1);
+
+  if (MasterAlarm.getInt() > WarnedLevel) {
+	QSound::play(QApplication::applicationDirPath() + "/Error.wav");
+
+    // Construct warning message box
+	QMessageBox Box;
+	Box.setWindowTitle("Edd Alarm");
+	Box.setText("Service 'Alarm/MasterAlarm' is at " + QString::number(MasterAlarm.getInt()));
+	Box.setInformativeText("Warn again for the same alarm level?");
+	Box.setIcon(QMessageBox::Warning);
+	Box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+	Box.setDefaultButton(QMessageBox::No);
+
+	// Check if user wants to reset warned level
+	if (Box.exec() == QMessageBox::Yes) WarnedLevel = 0;
+	else WarnedLevel = MasterAlarm.getInt();
+  }
+
+  // If MasterAlam decreased, lower also warned level
+  if (MasterAlarm.getInt() < WarnedLevel && MasterAlarm.getInt() >=0 ) WarnedLevel = MasterAlarm.getInt();
+  
+  // === Check Alarm server ===
+  DimCurrentInfo ServerList("DIS_DNS/SERVER_LIST", NO_LINK);
+  std::string Result = EvidenceServer::ToString((char *) "C", ServerList.getData(), ServerList.getSize());
+
+  // Warn if SERVER_LIST does not contain alarm server
+  if (Result.find("Alarm@") == std::string::npos && !AlarmServerWarned) {
+	QMessageBox Box;
+	Box.setWindowTitle("Edd Alarm");
+	Box.setText("Alarm server is unavailable or in error");
+	Box.setIcon(QMessageBox::Critical);
+	Box.setStandardButtons(QMessageBox::Ok);
+	Box.setDefaultButton(QMessageBox::Ok);
+	Box.exec();
+
+	AlarmServerWarned = true;
+  }
+  
+  if (Result.find("Alarm@") != std::string::npos) AlarmServerWarned = false; 
+}
+
+// Quit application when clicking close button on window
+void GUI::closeEvent(QCloseEvent *) {
+
+  qApp->quit();
+}
+
+
+//
+//**************************** Main program ***************************
+//
+int main(int argc, char *argv[]) {
+
+  if (argc>1 && strcmp(argv[1],"drsdaq")==0) DRSBoard = "drsdaq";
+
+  // EvidenceServer::ToString() works for structures only without padding
+  dic_disable_padding();
+  dis_disable_padding();
+
+  // Make RPC to get pixelmap
+  DimRpcInfo RPC((char *) "ConfigRequest", (char *) "");
+  RPC.setData((char *) "Misc PixelMap");
+  PixelMapText = std::string(RPC.getString(), RPC.getSize());
+
+  printf("Bulding GUI, requesting quick-look histories...\n");
+  QApplication app(argc, argv); 
+  GUI MainWindow;
+
+  return app.exec();
+}
Index: /fact/tools/Edd_LP/Edd.h
===================================================================
--- /fact/tools/Edd_LP/Edd.h	(revision 12940)
+++ /fact/tools/Edd_LP/Edd.h	(revision 12940)
@@ -0,0 +1,149 @@
+#ifndef EDD_H_SEEN
+#define EDD_H_SEEN
+
+#include "../../Evidence/GUI.h"
+#include "RawDataCTX.h"
+#include "PixelMap.h"
+
+#define SVN_REVISION "$Revision: 10143 $"
+
+class TP_DAQ;
+
+// Event oscilloscope
+class EventScope: public EddBasePlot, public PixelMap, public EddWidget {
+  Q_OBJECT
+
+  private:
+    struct ItemDetails {
+	  unsigned int Board, Chip, Channel;
+      QwtPlotCurve *Curve;
+	  QwtPlotMarker *Trigger;
+    };
+    QList<struct ItemDetails> List;
+
+	class TP_DAQ *DAQPage;
+    QString Name;
+	bool Active;
+	QAction *PhysPipeAction;
+	QAction *PersistanceAction;
+	FILE *Tmpfile;
+	QTemporaryFile File;
+	QString LastPath;
+
+  public:
+    EventScope(class TP_DAQ *, QWidget * = NULL);
+    ~EventScope();
+
+	void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int=-1);
+	void UpdateFirst(int, int, int);
+	void AddTrace(int, int, int);
+	void SetActive(bool);
+	QString ToPixel(unsigned int, unsigned int, unsigned int, unsigned int);
+	RawDataCTX *RD;
+	CTX_ErrCode ErrCode;
+
+  private slots:
+	void PlotTraces();
+	void NewEventNum(int);
+
+  public slots:
+	void OpenRawFile(QString=QString());
+	
+  signals:
+	void PixelData(QVector<double>);
+};
+
+
+// Tab page classes
+class TP_Environment: public QWidget {
+  Q_OBJECT
+
+  public:
+    TP_Environment();
+};
+
+class TP_Bias: public QWidget {
+  Q_OBJECT
+
+  public:
+    TP_Bias();
+};
+
+class TP_FADctrl: public QWidget {
+  Q_OBJECT
+
+  public:
+    TP_FADctrl();
+};
+
+class TP_Feedback: public QWidget {
+  Q_OBJECT
+
+  public:
+    TP_Feedback();
+};
+
+class TP_DAQ: public QWidget {
+  Q_OBJECT
+  static const int MAXPIXEL = 1440;
+
+  private:
+ 	QFormLayout *FormLayout;
+	QWidget *Display;
+	QPushButton **Pixel;
+	QPushButton *StartStopButton;
+
+  private slots:
+	void TranslatePixelID(int);
+	void UpdateScope(int);
+	void KeepCurrent();
+	void StartStop(bool);
+	void ShowPixelDisplay();
+	void SetPixelData(QVector<double>);
+	void OpenDataFile();
+
+  public:
+	TP_DAQ(bool);	
+	~TP_DAQ();
+	
+	EventScope *Scope;
+ 	QSpinBox *Channel, *Chip, *Board, *PixelID, *Event;
+    QPlainTextEdit *RunHeaderDisplay, *EventHeaderDisplay;
+	QLineEdit *FilenameBox;
+};
+
+class TP_Evidence: public QWidget {
+  Q_OBJECT
+
+  private slots:
+	void ToggleAlarm(bool);
+	void StartDIMBrowser();
+	void StartELog();
+
+  public:
+	TP_Evidence();	
+};
+
+
+// Main window class
+class GUI: public QMainWindow, public DimBrowser {
+  Q_OBJECT
+
+  private:
+    QTabWidget *TabWidget;
+            
+    void closeEvent(QCloseEvent *);
+	
+  public:
+    GUI();
+    
+  private slots:
+    void MenuAbout();
+    void MenuNewHistory();
+    void MenuCommand();
+    void MenuRawDataBrowser();
+	void DetachTab(int, bool=false);
+	void CheckAlarm();
+};
+
+#endif
Index: /fact/tools/Edd_LP/Edd.pro
===================================================================
--- /fact/tools/Edd_LP/Edd.pro	(revision 12940)
+++ /fact/tools/Edd_LP/Edd.pro	(revision 12940)
@@ -0,0 +1,10 @@
+
+TEMPLATE = app
+TARGET = 
+DEPENDPATH += .
+INCLUDEPATH += . ../../Evidence $(QWTDIR)/include $(DIMDIR)/dim ../../drsdaq ../../pixelmap
+
+# Input
+HEADERS += Edd.h ../../Evidence/GUI.h ../../Evidence/Evidence.h
+SOURCES += Edd.cc ../../Evidence/GUI.cc ../../Evidence/Evidence.cc ../../drsdaq/RawDataCTX.cc ../../pixelmap/Pixel.cc ../../pixelmap/PixelMap.cc
+LIBS += -L$(QWTDIR)/lib -lqwt $(DIMDIR)/linux/libdim.a
Index: /fact/tools/Edd_LP/moc_Edd.cpp
===================================================================
--- /fact/tools/Edd_LP/moc_Edd.cpp	(revision 12940)
+++ /fact/tools/Edd_LP/moc_Edd.cpp	(revision 12940)
@@ -0,0 +1,513 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'Edd.h'
+**
+** Created: Fri Feb 24 20:41:27 2012
+**      by: The Qt Meta Object Compiler version 62 (Qt 4.7.4)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "Edd.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'Edd.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 62
+#error "This file was generated using the moc from 4.7.4. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_EventScope[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       5,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       1,       // signalCount
+
+ // signals: signature, parameters, type, tag, flags
+      12,   11,   11,   11, 0x05,
+
+ // slots: signature, parameters, type, tag, flags
+      39,   11,   11,   11, 0x08,
+      52,   11,   11,   11, 0x08,
+      69,   11,   11,   11, 0x0a,
+      90,   11,   11,   11, 0x2a,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EventScope[] = {
+    "EventScope\0\0PixelData(QVector<double>)\0"
+    "PlotTraces()\0NewEventNum(int)\0"
+    "OpenRawFile(QString)\0OpenRawFile()\0"
+};
+
+const QMetaObject EventScope::staticMetaObject = {
+    { &EddBasePlot::staticMetaObject, qt_meta_stringdata_EventScope,
+      qt_meta_data_EventScope, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EventScope::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EventScope::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EventScope::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EventScope))
+        return static_cast<void*>(const_cast< EventScope*>(this));
+    if (!strcmp(_clname, "PixelMap"))
+        return static_cast< PixelMap*>(const_cast< EventScope*>(this));
+    if (!strcmp(_clname, "EddWidget"))
+        return static_cast< EddWidget*>(const_cast< EventScope*>(this));
+    return EddBasePlot::qt_metacast(_clname);
+}
+
+int EventScope::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = EddBasePlot::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: PixelData((*reinterpret_cast< QVector<double>(*)>(_a[1]))); break;
+        case 1: PlotTraces(); break;
+        case 2: NewEventNum((*reinterpret_cast< int(*)>(_a[1]))); break;
+        case 3: OpenRawFile((*reinterpret_cast< QString(*)>(_a[1]))); break;
+        case 4: OpenRawFile(); break;
+        default: ;
+        }
+        _id -= 5;
+    }
+    return _id;
+}
+
+// SIGNAL 0
+void EventScope::PixelData(QVector<double> _t1)
+{
+    void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
+    QMetaObject::activate(this, &staticMetaObject, 0, _a);
+}
+static const uint qt_meta_data_TP_Environment[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_TP_Environment[] = {
+    "TP_Environment\0"
+};
+
+const QMetaObject TP_Environment::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_TP_Environment,
+      qt_meta_data_TP_Environment, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &TP_Environment::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *TP_Environment::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *TP_Environment::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_TP_Environment))
+        return static_cast<void*>(const_cast< TP_Environment*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int TP_Environment::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+static const uint qt_meta_data_TP_Bias[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_TP_Bias[] = {
+    "TP_Bias\0"
+};
+
+const QMetaObject TP_Bias::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_TP_Bias,
+      qt_meta_data_TP_Bias, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &TP_Bias::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *TP_Bias::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *TP_Bias::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_TP_Bias))
+        return static_cast<void*>(const_cast< TP_Bias*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int TP_Bias::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+static const uint qt_meta_data_TP_FADctrl[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_TP_FADctrl[] = {
+    "TP_FADctrl\0"
+};
+
+const QMetaObject TP_FADctrl::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_TP_FADctrl,
+      qt_meta_data_TP_FADctrl, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &TP_FADctrl::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *TP_FADctrl::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *TP_FADctrl::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_TP_FADctrl))
+        return static_cast<void*>(const_cast< TP_FADctrl*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int TP_FADctrl::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+static const uint qt_meta_data_TP_Feedback[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_TP_Feedback[] = {
+    "TP_Feedback\0"
+};
+
+const QMetaObject TP_Feedback::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_TP_Feedback,
+      qt_meta_data_TP_Feedback, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &TP_Feedback::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *TP_Feedback::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *TP_Feedback::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_TP_Feedback))
+        return static_cast<void*>(const_cast< TP_Feedback*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int TP_Feedback::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+static const uint qt_meta_data_TP_DAQ[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       7,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+       8,    7,    7,    7, 0x08,
+      30,    7,    7,    7, 0x08,
+      47,    7,    7,    7, 0x08,
+      61,    7,    7,    7, 0x08,
+      77,    7,    7,    7, 0x08,
+      96,    7,    7,    7, 0x08,
+     126,    7,    7,    7, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_TP_DAQ[] = {
+    "TP_DAQ\0\0TranslatePixelID(int)\0"
+    "UpdateScope(int)\0KeepCurrent()\0"
+    "StartStop(bool)\0ShowPixelDisplay()\0"
+    "SetPixelData(QVector<double>)\0"
+    "OpenDataFile()\0"
+};
+
+const QMetaObject TP_DAQ::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_TP_DAQ,
+      qt_meta_data_TP_DAQ, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &TP_DAQ::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *TP_DAQ::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *TP_DAQ::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_TP_DAQ))
+        return static_cast<void*>(const_cast< TP_DAQ*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int TP_DAQ::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: TranslatePixelID((*reinterpret_cast< int(*)>(_a[1]))); break;
+        case 1: UpdateScope((*reinterpret_cast< int(*)>(_a[1]))); break;
+        case 2: KeepCurrent(); break;
+        case 3: StartStop((*reinterpret_cast< bool(*)>(_a[1]))); break;
+        case 4: ShowPixelDisplay(); break;
+        case 5: SetPixelData((*reinterpret_cast< QVector<double>(*)>(_a[1]))); break;
+        case 6: OpenDataFile(); break;
+        default: ;
+        }
+        _id -= 7;
+    }
+    return _id;
+}
+static const uint qt_meta_data_TP_Evidence[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       3,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+      13,   12,   12,   12, 0x08,
+      31,   12,   12,   12, 0x08,
+      49,   12,   12,   12, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_TP_Evidence[] = {
+    "TP_Evidence\0\0ToggleAlarm(bool)\0"
+    "StartDIMBrowser()\0StartELog()\0"
+};
+
+const QMetaObject TP_Evidence::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_TP_Evidence,
+      qt_meta_data_TP_Evidence, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &TP_Evidence::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *TP_Evidence::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *TP_Evidence::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_TP_Evidence))
+        return static_cast<void*>(const_cast< TP_Evidence*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int TP_Evidence::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: ToggleAlarm((*reinterpret_cast< bool(*)>(_a[1]))); break;
+        case 1: StartDIMBrowser(); break;
+        case 2: StartELog(); break;
+        default: ;
+        }
+        _id -= 3;
+    }
+    return _id;
+}
+static const uint qt_meta_data_GUI[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       7,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+       5,    4,    4,    4, 0x08,
+      17,    4,    4,    4, 0x08,
+      34,    4,    4,    4, 0x08,
+      48,    4,    4,    4, 0x08,
+      71,   69,    4,    4, 0x08,
+      91,    4,    4,    4, 0x28,
+     106,    4,    4,    4, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_GUI[] = {
+    "GUI\0\0MenuAbout()\0MenuNewHistory()\0"
+    "MenuCommand()\0MenuRawDataBrowser()\0,\0"
+    "DetachTab(int,bool)\0DetachTab(int)\0"
+    "CheckAlarm()\0"
+};
+
+const QMetaObject GUI::staticMetaObject = {
+    { &QMainWindow::staticMetaObject, qt_meta_stringdata_GUI,
+      qt_meta_data_GUI, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &GUI::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *GUI::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *GUI::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_GUI))
+        return static_cast<void*>(const_cast< GUI*>(this));
+    if (!strcmp(_clname, "DimBrowser"))
+        return static_cast< DimBrowser*>(const_cast< GUI*>(this));
+    return QMainWindow::qt_metacast(_clname);
+}
+
+int GUI::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QMainWindow::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: MenuAbout(); break;
+        case 1: MenuNewHistory(); break;
+        case 2: MenuCommand(); break;
+        case 3: MenuRawDataBrowser(); break;
+        case 4: DetachTab((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< bool(*)>(_a[2]))); break;
+        case 5: DetachTab((*reinterpret_cast< int(*)>(_a[1]))); break;
+        case 6: CheckAlarm(); break;
+        default: ;
+        }
+        _id -= 7;
+    }
+    return _id;
+}
+QT_END_MOC_NAMESPACE
Index: /fact/tools/Edd_LP/moc_GUI.cpp
===================================================================
--- /fact/tools/Edd_LP/moc_GUI.cpp	(revision 12940)
+++ /fact/tools/Edd_LP/moc_GUI.cpp	(revision 12940)
@@ -0,0 +1,573 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'GUI.h'
+**
+** Created: Fri Feb 24 20:41:29 2012
+**      by: The Qt Meta Object Compiler version 62 (Qt 4.7.4)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "../../Evidence/GUI.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'GUI.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 62
+#error "This file was generated using the moc from 4.7.4. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_EddBasePlot[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+      11,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+      13,   12,   12,   12, 0x09,
+      26,   12,   12,   12, 0x08,
+      38,   12,   12,   12, 0x08,
+      64,   12,   12,   12, 0x08,
+      91,   12,   12,   12, 0x08,
+     128,   12,   12,   12, 0x08,
+     148,   12,   12,   12, 0x08,
+     162,   12,   12,   12, 0x08,
+     178,   12,   12,   12, 0x08,
+     189,   12,   12,   12, 0x08,
+     201,   12,   12,   12, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddBasePlot[] = {
+    "EddBasePlot\0\0UpdatePlot()\0ReDoStats()\0"
+    "HandleZoom(QwtDoubleRect)\0"
+    "MouseSelection(QwtPolygon)\0"
+    "contextMenuEvent(QContextMenuEvent*)\0"
+    "MenuSetUpdateRate()\0MenuZoomOut()\0"
+    "MenuSaveASCII()\0MenuSave()\0MenuPrint()\0"
+    "MenuPlotHelp()\0"
+};
+
+const QMetaObject EddBasePlot::staticMetaObject = {
+    { &QwtPlot::staticMetaObject, qt_meta_stringdata_EddBasePlot,
+      qt_meta_data_EddBasePlot, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddBasePlot::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddBasePlot::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddBasePlot::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddBasePlot))
+        return static_cast<void*>(const_cast< EddBasePlot*>(this));
+    return QwtPlot::qt_metacast(_clname);
+}
+
+int EddBasePlot::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QwtPlot::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: UpdatePlot(); break;
+        case 1: ReDoStats(); break;
+        case 2: HandleZoom((*reinterpret_cast< const QwtDoubleRect(*)>(_a[1]))); break;
+        case 3: MouseSelection((*reinterpret_cast< const QwtPolygon(*)>(_a[1]))); break;
+        case 4: contextMenuEvent((*reinterpret_cast< QContextMenuEvent*(*)>(_a[1]))); break;
+        case 5: MenuSetUpdateRate(); break;
+        case 6: MenuZoomOut(); break;
+        case 7: MenuSaveASCII(); break;
+        case 8: MenuSave(); break;
+        case 9: MenuPrint(); break;
+        case 10: MenuPlotHelp(); break;
+        default: ;
+        }
+        _id -= 11;
+    }
+    return _id;
+}
+static const uint qt_meta_data_EddLineDisplay[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       4,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+      16,   15,   15,   15, 0x08,
+      53,   15,   15,   15, 0x08,
+      71,   15,   15,   15, 0x08,
+      89,   15,   15,   15, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddLineDisplay[] = {
+    "EddLineDisplay\0\0contextMenuEvent(QContextMenuEvent*)\0"
+    "MenuOpenHistory()\0MenuCopyService()\0"
+    "MenuCopyData()\0"
+};
+
+const QMetaObject EddLineDisplay::staticMetaObject = {
+    { &QLineEdit::staticMetaObject, qt_meta_stringdata_EddLineDisplay,
+      qt_meta_data_EddLineDisplay, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddLineDisplay::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddLineDisplay::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddLineDisplay::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddLineDisplay))
+        return static_cast<void*>(const_cast< EddLineDisplay*>(this));
+    if (!strcmp(_clname, "EddWidget"))
+        return static_cast< EddWidget*>(const_cast< EddLineDisplay*>(this));
+    return QLineEdit::qt_metacast(_clname);
+}
+
+int EddLineDisplay::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QLineEdit::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: contextMenuEvent((*reinterpret_cast< QContextMenuEvent*(*)>(_a[1]))); break;
+        case 1: MenuOpenHistory(); break;
+        case 2: MenuCopyService(); break;
+        case 3: MenuCopyData(); break;
+        default: ;
+        }
+        _id -= 4;
+    }
+    return _id;
+}
+static const uint qt_meta_data_EddCommand[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       3,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+      12,   11,   11,   11, 0x08,
+      26,   11,   11,   11, 0x08,
+      63,   11,   11,   11, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddCommand[] = {
+    "EddCommand\0\0SendCommand()\0"
+    "contextMenuEvent(QContextMenuEvent*)\0"
+    "MenuCommandHelp()\0"
+};
+
+const QMetaObject EddCommand::staticMetaObject = {
+    { &QLineEdit::staticMetaObject, qt_meta_stringdata_EddCommand,
+      qt_meta_data_EddCommand, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddCommand::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddCommand::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddCommand::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddCommand))
+        return static_cast<void*>(const_cast< EddCommand*>(this));
+    return QLineEdit::qt_metacast(_clname);
+}
+
+int EddCommand::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QLineEdit::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: SendCommand(); break;
+        case 1: contextMenuEvent((*reinterpret_cast< QContextMenuEvent*(*)>(_a[1]))); break;
+        case 2: MenuCommandHelp(); break;
+        default: ;
+        }
+        _id -= 3;
+    }
+    return _id;
+}
+static const uint qt_meta_data_EddPlot[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       5,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+       9,    8,    8,    8, 0x0a,
+      38,    8,    8,    8, 0x08,
+      57,    8,    8,    8, 0x08,
+      76,    8,    8,    8, 0x08,
+      94,    8,    8,    8, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddPlot[] = {
+    "EddPlot\0\0RemoveService(QwtPlotCurve*)\0"
+    "MenuPasteService()\0MenuShowLastHour()\0"
+    "MenuShowLastDay()\0MenuAllAsText()\0"
+};
+
+const QMetaObject EddPlot::staticMetaObject = {
+    { &EddBasePlot::staticMetaObject, qt_meta_stringdata_EddPlot,
+      qt_meta_data_EddPlot, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddPlot::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddPlot::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddPlot::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddPlot))
+        return static_cast<void*>(const_cast< EddPlot*>(this));
+    if (!strcmp(_clname, "EddWidget"))
+        return static_cast< EddWidget*>(const_cast< EddPlot*>(this));
+    return EddBasePlot::qt_metacast(_clname);
+}
+
+int EddPlot::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = EddBasePlot::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: RemoveService((*reinterpret_cast< QwtPlotCurve*(*)>(_a[1]))); break;
+        case 1: MenuPasteService(); break;
+        case 2: MenuShowLastHour(); break;
+        case 3: MenuShowLastDay(); break;
+        case 4: MenuAllAsText(); break;
+        default: ;
+        }
+        _id -= 5;
+    }
+    return _id;
+}
+static const uint qt_meta_data_EddLegend[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       6,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       1,       // signalCount
+
+ // signals: signature, parameters, type, tag, flags
+      11,   10,   10,   10, 0x05,
+
+ // slots: signature, parameters, type, tag, flags
+      38,   10,   10,   10, 0x08,
+      56,   10,   10,   10, 0x08,
+      74,   10,   10,   10, 0x08,
+      91,   10,   10,   10, 0x08,
+     107,   10,   10,   10, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddLegend[] = {
+    "EddLegend\0\0DeleteCurve(QwtPlotCurve*)\0"
+    "MenuOpenHistory()\0MenuCopyService()\0"
+    "MenuNormalLine()\0MenuThickLine()\0"
+    "MenuRemove()\0"
+};
+
+const QMetaObject EddLegend::staticMetaObject = {
+    { &QwtLegendItem::staticMetaObject, qt_meta_stringdata_EddLegend,
+      qt_meta_data_EddLegend, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddLegend::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddLegend::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddLegend::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddLegend))
+        return static_cast<void*>(const_cast< EddLegend*>(this));
+    return QwtLegendItem::qt_metacast(_clname);
+}
+
+int EddLegend::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QwtLegendItem::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: DeleteCurve((*reinterpret_cast< QwtPlotCurve*(*)>(_a[1]))); break;
+        case 1: MenuOpenHistory(); break;
+        case 2: MenuCopyService(); break;
+        case 3: MenuNormalLine(); break;
+        case 4: MenuThickLine(); break;
+        case 5: MenuRemove(); break;
+        default: ;
+        }
+        _id -= 6;
+    }
+    return _id;
+}
+
+// SIGNAL 0
+void EddLegend::DeleteCurve(QwtPlotCurve * _t1)
+{
+    void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
+    QMetaObject::activate(this, &staticMetaObject, 0, _a);
+}
+static const uint qt_meta_data_EddText[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddText[] = {
+    "EddText\0"
+};
+
+const QMetaObject EddText::staticMetaObject = {
+    { &QTextEdit::staticMetaObject, qt_meta_stringdata_EddText,
+      qt_meta_data_EddText, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddText::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddText::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddText::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddText))
+        return static_cast<void*>(const_cast< EddText*>(this));
+    if (!strcmp(_clname, "EddWidget"))
+        return static_cast< EddWidget*>(const_cast< EddText*>(this));
+    return QTextEdit::qt_metacast(_clname);
+}
+
+int EddText::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QTextEdit::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+static const uint qt_meta_data_EddDim[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       5,   14, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       3,       // signalCount
+
+ // signals: signature, parameters, type, tag, flags
+      12,    8,    7,    7, 0x05,
+      51,   48,    7,    7, 0x25,
+      81,   79,    7,    7, 0x25,
+
+ // slots: signature, parameters, type, tag, flags
+      98,    8,    7,    7, 0x08,
+     137,    7,    7,    7, 0x08,
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddDim[] = {
+    "EddDim\0\0,,,\0INT(QString,int,QByteArray,QString)\0"
+    ",,\0INT(QString,int,QByteArray)\0,\0"
+    "INT(QString,int)\0"
+    "Update(QString,int,QByteArray,QString)\0"
+    "UpdateStatistics()\0"
+};
+
+const QMetaObject EddDim::staticMetaObject = {
+    { &QObject::staticMetaObject, qt_meta_stringdata_EddDim,
+      qt_meta_data_EddDim, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddDim::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddDim::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddDim::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddDim))
+        return static_cast<void*>(const_cast< EddDim*>(this));
+    if (!strcmp(_clname, "DimInfo"))
+        return static_cast< DimInfo*>(const_cast< EddDim*>(this));
+    return QObject::qt_metacast(_clname);
+}
+
+int EddDim::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QObject::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    if (_c == QMetaObject::InvokeMetaMethod) {
+        switch (_id) {
+        case 0: INT((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< QByteArray(*)>(_a[3])),(*reinterpret_cast< QString(*)>(_a[4]))); break;
+        case 1: INT((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< QByteArray(*)>(_a[3]))); break;
+        case 2: INT((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
+        case 3: Update((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< QByteArray(*)>(_a[3])),(*reinterpret_cast< QString(*)>(_a[4]))); break;
+        case 4: UpdateStatistics(); break;
+        default: ;
+        }
+        _id -= 5;
+    }
+    return _id;
+}
+
+// SIGNAL 0
+void EddDim::INT(QString _t1, int _t2, QByteArray _t3, QString _t4)
+{
+    void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)), const_cast<void*>(reinterpret_cast<const void*>(&_t3)), const_cast<void*>(reinterpret_cast<const void*>(&_t4)) };
+    QMetaObject::activate(this, &staticMetaObject, 0, _a);
+}
+static const uint qt_meta_data_EddWindow[] = {
+
+ // content:
+       5,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+static const char qt_meta_stringdata_EddWindow[] = {
+    "EddWindow\0"
+};
+
+const QMetaObject EddWindow::staticMetaObject = {
+    { &QPushButton::staticMetaObject, qt_meta_stringdata_EddWindow,
+      qt_meta_data_EddWindow, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &EddWindow::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *EddWindow::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *EddWindow::qt_metacast(const char *_clname)
+{
+    if (!_clname) return 0;
+    if (!strcmp(_clname, qt_meta_stringdata_EddWindow))
+        return static_cast<void*>(const_cast< EddWindow*>(this));
+    return QPushButton::qt_metacast(_clname);
+}
+
+int EddWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QPushButton::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+QT_END_MOC_NAMESPACE
