Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 139)
+++ Evidence/Edd/Edd.cc	(revision 142)
@@ -1,2 +1,3 @@
+
 /* ============================================================ 
 
@@ -19,4 +20,6 @@
 	Qt::gray, Qt::darkGray, Qt::lightGray};
 
+class GUI *Handler;
+
 //////////////////////////////////////////
 // Text display for arbitary DIM service//
@@ -26,17 +29,21 @@
 Edd_Indicator::Edd_Indicator(QString DIMService, QWidget *P): QLineEdit(P) {
 
-  ServiceName = qstrdup(DIMService.toAscii().data());
-  
   // Widget properties
   setReadOnly(true);
   setMaximumWidth(100);
-  connect(this, SIGNAL(YEP(QString)), this, SLOT(setText(QString)));
+  ShowAsTime = false;
+  
+  // Connect to DIM handler
+  if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QString, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {
+    printf("Failed connection for %s\n", DIMService.toAscii().data());
+  }
 
   // Context menu
   Menu = new QMenu(this);
+  Menu->addAction("Open history", this, SLOT(MenuOpenHistory()));
   Menu->addAction("Copy service", this, SLOT(MenuCopyService()));
 
   // DIM client
-  Data = new DimStampedInfo(ServiceName, INT_MAX, (char *) NO_LINK, this);
+  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *) NO_LINK, Handler);
 }
 
@@ -44,54 +51,40 @@
 Edd_Indicator::~Edd_Indicator() {
   delete Data;
-  delete[] ServiceName;
-}
-
-// Handling of DIM service update
-void Edd_Indicator::infoHandler() {
-
+}
+
+// Update widget
+void Edd_Indicator::Update(DimInfo *Info, int Time, QString Format, QByteArray Data, QString Text) {
+
+  if (Info != this->Data) return;
+    
   QPalette Pal = palette();  
-  QString S;
 
   // Check if service available
-  if (getInfo()->getSize() == strlen(NO_LINK)+1 && strcmp(getInfo()->getString(), NO_LINK) == 0) {
-    emit(YEP(QString("n/a")));
-    setStatusTip(QString("%1:  unavailable").arg(ServiceName));
-    Pal.setColor(backgroundRole(), Qt::red);
-    setPalette(Pal);
-    return;
-  }
-  Pal.setColor(backgroundRole(), Qt::white);
-
-  // Translate data into ASCII
-  char *Text = EvidenceServer::ToString(getInfo());
-
-  // If this is a status indicator, adapt background colour
-  if (getInfo()->getSize() == (int) strlen(Text)+3) {
-    switch (*((char *) getInfo()->getData() + strlen(Text) + 2)) {
-      case 0:  Pal.setColor(backgroundRole(), Qt::white); break;
-      case 1:  Pal.setColor(backgroundRole(), Qt::cyan); break;
-      case 2:  Pal.setColor(backgroundRole(), Qt::red); break;
-      case 3:  Pal.setColor(backgroundRole(), Qt::red); break;
-      default: break;
-    }
-  }
+  if (Time == -1) {
+    setText("n/a");
+	setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
+    Pal.setColor(QPalette::Base, Qt::lightGray);
+  }
+  else {
+    // If this is a status indicator, adapt background colour
+    if (Data.size() == Text.size()+2) {
+      switch (Data[Text.size() + 2]) {
+        case 0:  Pal.setColor(QPalette::Base, Qt::white); break;
+        case 1:  Pal.setColor(QPalette::Base, Qt::cyan); break;
+        case 2:  Pal.setColor(QPalette::Base, Qt::red); break;
+        case 3:  Pal.setColor(QPalette::Base, Qt::red); break;
+        default: break;
+      }
+    }
+    else Pal.setColor(QPalette::Base, Qt::white);
+	
+	if (!ShowAsTime) setText(Text);
+	else setText(QDateTime::fromTime_t(Text.toInt()).toString());
+	
+    // Update status tip
+    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Format));
+  }
+  
   setPalette(Pal);
-  
-  if (Text != NULL) {
-    QTextStream(&S) << Text;
-	free(Text);
-  }
-  else QTextStream(&S) << "Cannot interpret format identifier";
-    
-  if (strlen(getInfo()->getFormat()) > 1) {
-    QTextStream(&S) << " (DIM format string longer)";
-  }
-  
-  // Trigger display update
-  emit(YEP(S));
-  
-  // Update status tip
-  QDateTime Time = QDateTime::fromTime_t(getInfo()->getTimestamp()); 
-  setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(ServiceName, Time.toString()).arg(getInfo()->getFormat()));
 }
 
@@ -111,6 +104,5 @@
 
   // If not, open new plot
-  LastPlot = new Edd_Plot(ServiceName);
-  LastPlot->show();
+  Edd_Indicator::MenuOpenHistory();
 }
 
@@ -129,5 +121,5 @@
   QDrag *Drag = new QDrag(this);
   QMimeData *MimeData = new QMimeData;
-  MimeData->setText(QString(ServiceName));
+  MimeData->setText(QString(Data->getName()));
   Drag->setMimeData(MimeData);
   Drag->exec();
@@ -142,8 +134,15 @@
 }
 
+// Open history plot
+void Edd_Indicator::MenuOpenHistory() {
+  
+  LastPlot = new Edd_Plot(Data->getName());
+  LastPlot->show();
+}
+
 // Copy service name
 void Edd_Indicator::MenuCopyService() {
   
-  QApplication::clipboard()->setText(QString(ServiceName));
+  QApplication::clipboard()->setText(QString(Data->getName()));
 }
 
@@ -161,10 +160,10 @@
   
   // Graph properties
-  QwtText XAxisTitle("Time (RJD-55000)");
+  setAutoReplot(false);
+  QwtText XAxisTitle("Time (RJD-55200)");
   XAxisTitle.setFont(QFont("Helvetica", 10));
   setAxisTitle(QwtPlot::xBottom, XAxisTitle);
-  setAutoReplot(false);
   setCanvasBackground(QColor(Qt::yellow));
-  
+
   Zoomer = new QwtPlotZoomer(QwtPlot::xBottom,QwtPlot::yLeft,canvas());
   connect(Zoomer, SIGNAL(zoomed(const QwtDoubleRect &)), this, SLOT(HandleZoom(const QwtDoubleRect &)));
@@ -176,7 +175,9 @@
   Legend = new QwtLegend();
   insertLegend(Legend, QwtPlot::TopLegend);
-    
-  // Threads may not call replot directly, but only through this signal
-  connect(this, SIGNAL(YEP()), this, SLOT(UpdatePlot()));
+
+  // Connect to DIM handler
+  if (connect(Handler, SIGNAL(YEP(DimInfo *, int, QString, QByteArray, QString)), SLOT(Update(DimInfo *, int, QString, QByteArray, QString))) == false) {
+    printf("Failed connection for %s\n", DIMService.toAscii().data());
+  }
 
   // Context menu
@@ -222,5 +223,5 @@
 
   QString HistName = Name+".hist";
-  
+
   // Lock before accessing Items list
   QMutexLocker Locker(&Mutex);
@@ -233,5 +234,5 @@
     }
   }  
-
+  
   // Generate new curve and subscribe to service
   struct PlotItem New;
@@ -239,23 +240,20 @@
   New.Signal->attach(this);
   New.Signal->setTitle(HistName);
-  New.Signal->setPen(QColor(LineColors[Items.size()%(sizeof(LineColors)/sizeof(Qt::GlobalColor))]));
+  New.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))]));
   New.x = NULL;
   New.y = NULL;
   New.Count = 0;
-  New.Data = new DimStampedInfo(HistName.toAscii(), NO_LINK, this); 
-  New.LiveData = new DimStampedInfo(Name.toAscii(), NO_LINK, this); 
+  New.Data = new DimStampedInfo(HistName.toAscii().data(), (char *) NO_LINK, Handler);
+  New.LiveData = new DimStampedInfo(Name.toAscii().data(), (char *) NO_LINK, Handler); 
 
   Items.append(New);
 }
 
-//
-// Handle update of DIM service
-//
-void Edd_Plot::infoHandler() {
+// Update widget (must happen in GUI thread)
+void Edd_Plot::Update(DimInfo *Info, int Time, QString Format, QByteArray Data, QString Text) {
 
   // Check if service available
-  if (getInfo()->getSize() == strlen(NO_LINK)+1 && strcmp(getInfo()->getString(), NO_LINK) == 0) {
-    setStatusTip(QString("%1:  unavailable").arg(getInfo()->getName()));
-    return;
+  if (Time == -1) {
+	setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
   }
 
@@ -265,8 +263,8 @@
   // Determine which plot item this call belongs to
   int ItemNo;
-  for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Items[ItemNo].Data == getInfo()) {
+  for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Info == Items[ItemNo].Data) {
     // This is a history service  
-    EvidenceHistoryItem *Curr = (EvidenceHistoryItem *) getInfo()->getData();
-    int Count=0, DataPoints = getInfo()->getSize()/sizeof(struct EvidenceHistoryItem);
+    EvidenceHistoryItem *Curr = (EvidenceHistoryItem *) Data.data();
+    int Count=0, DataPoints = Data.size()/sizeof(struct EvidenceHistoryItem);
 
     delete[] Items[ItemNo].x;
@@ -302,8 +300,8 @@
 
     // Update status tip
-    QDateTime Time = QDateTime::fromTime_t(getInfo()->getTimestamp()); 
-    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(getInfo()->getName(), Time.toString()).arg(getInfo()->getFormat()));
-
-  } else if (Items[ItemNo].LiveData == getInfo()) {
+    QDateTime Timex = QDateTime::fromTime_t(Time); 
+    StatusTip = QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), Timex.toString()).arg(Format);
+
+  } else if (Info == Items[ItemNo].LiveData) {
     // This is a live service 
 
@@ -313,8 +311,8 @@
     // Append data
     struct EvidenceHistoryItem Data;
-    Data.Seconds = getInfo()->getTimestamp();
-    Data.Value = atof(EvidenceServer::ToString(getInfo()));            
+    Data.Seconds = Time;
+    Data.Value = atof(Text.toAscii().data());            
     Items[ItemNo].Live.append(Data);
-    
+
     // Update largest and smallest value    
     if (Data.Value > Items[ItemNo].Largest) Items[ItemNo].Largest = Data.Value;
@@ -324,8 +322,6 @@
   Locker.unlock();
 
-  // Do not call replot() directly from this thread!
-  emit(YEP());
-}
-
+  UpdatePlot();
+}
 
 //
@@ -333,4 +329,8 @@
 //
 void Edd_Plot::UpdatePlot() {
+
+  static QwtSymbol Symbol, Sym1;
+  Symbol.setStyle(QwtSymbol::Ellipse);
+  Symbol.setSize(4);
 
   if (!YLogAction->isChecked()) {
@@ -342,23 +342,26 @@
   QMutexLocker Locker(&Mutex);
 
+  setStatusTip(StatusTip);
+  
   for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
 
-    if (Items[ItemNo].Count == 0) continue;
-
-    if (StyleAction->isChecked()) Items[ItemNo].Signal->setStyle(QwtPlotCurve::Dots);
-    else Items[ItemNo].Signal->setStyle(QwtPlotCurve::Lines);
-
-    int DataPoints = Items[ItemNo].Count + Items[ItemNo].Live.size();      
+    if (StyleAction->isChecked()) Items[ItemNo].Signal->setSymbol(Symbol);
+    else Items[ItemNo].Signal->setSymbol(Sym1);
+
+    int DataPoints = Items[ItemNo].Count + Items[ItemNo].Live.size();
+	
+	if (DataPoints == 0) continue;
+   
     double *x = new double [DataPoints];
     double *y = new double [DataPoints];
-    
+ 
     // Adapt time scale and normalize y scale if requested
     for (int i=0; i<DataPoints; i++) {
       if (i < Items[ItemNo].Count) {
-        x[i] = Items[ItemNo].x[i] / 86400.0 + 40587.5 - 55000;
+        x[i] = Items[ItemNo].x[i] / 86400.0 + 40587.5 - 55200;
         y[i] = Items[ItemNo].y[i];
       }
       else {
-        x[i]= Items[ItemNo].Live[i-Items[ItemNo].Count].Seconds / 86400.0 + 40587.5 - 55000;
+        x[i]= Items[ItemNo].Live[i-Items[ItemNo].Count].Seconds / 86400.0 + 40587.5 - 55200;
         y[i] = Items[ItemNo].Live[i-Items[ItemNo].Count].Value;
       }
@@ -498,12 +501,66 @@
 
 
+//////////////////
+// Text display //
+//////////////////
+
+// Constructor
+Edd_Textout::Edd_Textout(QString DIMService, QWidget *P): QTextEdit(P) {
+
+  // Widget properties
+  setReadOnly(true);
+  setAutoFillBackground(true);
+  document()->setMaximumBlockCount(1000);
+  Accumulate = true;
+  
+  // Connect to DIM handler
+  if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QString, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {
+    printf("Failed connection for %s\n", DIMService.toAscii().data());
+  }
+
+  // DIM client
+  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *) NO_LINK, Handler);
+}
+
+// Destructor
+Edd_Textout::~Edd_Textout() {
+
+  delete Data;
+}
+
+// Handling of DIM service update
+void Edd_Textout::Update(DimInfo *Info, int Time, QString Format, QByteArray, QString Text) {
+
+  if (Info != this->Data) return;
+  
+  QPalette Pal = palette();  
+
+  // Check if service available
+  if (Time == -1) {
+	setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
+    Pal.setColor(QPalette::Base, Qt::lightGray);
+  }
+  else {
+    Pal.setColor(QPalette::Base, Qt::white);
+
+	// Clear display in case text should not accumulate
+	if (Accumulate == false) clear();
+	
+    // Add if service contains only a string
+    if (Format == "C") insertPlainText(Text);
+
+    // Update status tip
+    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Format));
+  }
+  setPalette(Pal);
+}
+
+
 //
 // Main GUI (all widgets have ultimately Central as parent)
 //
 GUI::GUI() {
-
-  Edd_Indicator *Value;
-  Edd_Plot *Graph;
-  QString Text;
+ 
+  Handler = this;
   
   // Set features of main window
@@ -511,5 +568,12 @@
   setCentralWidget(Central);
   setStatusBar(new QStatusBar(this));
-  
+  setGeometry(100, 100, 800, 650);
+  setWindowTitle("Edd - Evidence Data Display");
+
+  Edd_Indicator *Value;
+  Edd_Plot *Graph;
+  Edd_Textout *Textout; 
+  QString Text;
+
    // TextBox for value
   //Value = new Edd_Indicator((char *) "SQM/NSB", Central);
@@ -532,4 +596,22 @@
   MainWidget = new QWidget();
   MainLayout = new QGridLayout(MainWidget);
+
+  Value = new Edd_Indicator("DColl/DataSizekB");
+  MainLayout->addWidget(Value, 3, 5, 1, 1);
+
+  Value = new Edd_Indicator("DColl/LogSizekB");
+  MainLayout->addWidget(Value, 4, 5, 1, 1);
+
+  Value = new Edd_Indicator("Config/ModifyTime");
+  Value->setMaximumWidth(200);
+  Value->ShowAsTime = true;
+  MainLayout->addWidget(Value, 5, 5, 1, 1);
+
+  Value = new Edd_Indicator("Alarm/MasterAlarm");
+  MainLayout->addWidget(Value, 2, 0, 1, 1);
+
+  Textout = new Edd_Textout("Alarm/Summary");
+  Textout->Accumulate = false;
+  MainLayout->addWidget(Textout, 3, 0, 2, 1);
 
   // Layout of all widgets
@@ -557,4 +639,5 @@
     Graph->AddService(Text);
   }
+
   BiasLayout->addWidget(Graph, 0, 4, 12, 3);
   Value = new Edd_Indicator("BIAS/Status");
@@ -562,4 +645,8 @@
   BiasLayout->addWidget(Value, 0, 0, 1, 3);      
 
+  Textout = new Edd_Textout("BIAS/Textout");
+  Textout->setFixedWidth(400);
+  BiasLayout->addWidget(Textout, 10, 0, 4, 4);      
+  
   // Environment page
   EnvironmentWidget = new QWidget();
@@ -580,5 +667,5 @@
   Value = new Edd_Indicator("SQM/NSB");
   EnvironmentLayout->addWidget(Value, 6, 0, 1, 1);      
-    
+
   // Tab widget
   TabWidget = new QTabWidget(Central);
@@ -595,4 +682,7 @@
   QAction* QuitAction = Menu->addAction("Quit", qApp, SLOT(quit()));
   QuitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
+
+  // Show main window
+  show();
 }  
     
@@ -601,12 +691,13 @@
 }
 
+
 void GUI::MenuAbout() {
   QString Rev(SVN_REVISION);
-  Rev.remove(0,1).chop(1);
+  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.\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.");
@@ -639,4 +730,19 @@
 }
 
+// Handling of DIM service update
+void GUI::infoHandler() {
+
+  // Check if service available
+  if (getInfo()->getSize() == strlen(NO_LINK)+1 && strcmp(getInfo()->getString(), NO_LINK) == 0) {
+    YEP(getInfo(), -1);
+  }
+  else {
+    char *Txt = EvidenceServer::ToString(getInfo());
+
+    YEP(getInfo(), getInfo()->getTimestamp(), getInfo()->getFormat(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt));
+		free(Txt);
+  }
+}
+
 //---------------------------------------------------------------------
 //************************ All functions ****************************
@@ -654,11 +760,8 @@
 
 int main(int argc, char *argv[]) {
-  QApplication app(argc, argv);
-  
+
+  QApplication app(argc, argv); 
   GUI MainWindow;
-  MainWindow.setGeometry(100, 100, 800, 650);
-  MainWindow.setWindowTitle("Edd - Evidence Data Display");
-  MainWindow.show();
-  
+
   return app.exec();
 }
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 139)
+++ Evidence/Edd/Edd.h	(revision 142)
@@ -15,4 +15,5 @@
 #include <qwt_legend.h>
 #include <qwt_legend_item.h>
+#include <qwt_symbol.h>
 
 #include <limits.h>
@@ -22,19 +23,16 @@
 #include "Evidence.h"
 
-#define NO_LINK "__&DIM&NOLINK&__" // for checking if DIMserver is alive
 #define SVN_REVISION "$Revision$"
 		  
 // General indicator for DIM service
-class Edd_Indicator: public QLineEdit, public DimClient, public DimBrowser {
+class Edd_Indicator: public QLineEdit, public DimClient {
     Q_OBJECT
-
-    char *ServiceName;
-    DimStampedInfo *Data;
 
     QMenu *Menu;
     QPoint dragStart;
     QwtPlot *LastPlot;
-    	
-    void infoHandler();
+	
+    DimStampedInfo *Data;
+	
     void mousePressEvent(QMouseEvent *); 
     void mouseReleaseEvent(QMouseEvent *); 
@@ -45,10 +43,11 @@
     ~Edd_Indicator();
 
+	bool ShowAsTime;
+	
   private slots:
+	void Update(DimInfo *, int, QString, QByteArray, QString);
     void contextMenuEvent(QContextMenuEvent *);    
+    void MenuOpenHistory();
     void MenuCopyService();
-
-  signals:
-    void YEP(QString);
 };
 
@@ -72,4 +71,6 @@
     QMutex Mutex;
     
+	QString StatusTip;
+	
     QMenu *Menu;
     QAction *YLogAction;
@@ -82,5 +83,4 @@
     QwtLegend *Legend;
     
-    void infoHandler();    
     void dragEnterEvent(QDragEnterEvent *);
     void dropEvent(QDropEvent *);
@@ -93,4 +93,6 @@
   private slots:
     void UpdatePlot();
+	void Update(DimInfo* Info, int, QString, QByteArray, QString);
+
     void HandleZoom(const QwtDoubleRect &);
     void contextMenuEvent(QContextMenuEvent *);    
@@ -101,12 +103,24 @@
     void MenuPrint();
     void MenuPasteService();
- 
- signals:
-     void YEP();
+};
 
+// Textout indicator for DIM service
+class Edd_Textout: public QTextEdit, public DimClient {
+    Q_OBJECT
+
+    DimStampedInfo *Data;
+
+  public:
+    Edd_Textout(QString, QWidget * = NULL);
+    ~Edd_Textout();
+	
+	bool Accumulate;
+	
+  private slots:
+	void Update(DimInfo* Info, int, QString, QByteArray, QString);
 };
 
 // Main window class
-class GUI: public QMainWindow, public DimBrowser {
+class GUI: public QMainWindow, public DimBrowser, public DimInfo {
     Q_OBJECT
 
@@ -118,6 +132,7 @@
     QTabWidget *TabWidget;
             
-    void closeEvent(QCloseEvent *); 
-
+    void closeEvent(QCloseEvent *);
+	void infoHandler();
+	
   public:
     GUI();
@@ -127,4 +142,7 @@
     void MenuAbout();
     void MenuNewHistory();
+	
+  signals:
+    void YEP(DimInfo *, int, QString = QString(), QByteArray = QByteArray(), QString = QString());
 };
 
