Changeset 12940 for fact/Evidence


Ignore:
Timestamp:
02/24/12 20:43:27 (13 years ago)
Author:
ogrimm
Message:
History handling in Edd faster, improved drag and drop functionality, version of Edd for La Palma
Location:
fact/Evidence
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • fact/Evidence/GUI.cc

    r12910 r12940  
    2323  QString Format;
    2424  DimBrowser Browser;
    25   class EvidenceHistory *Hist = Handler->GetHistory(Service);
     25  struct EddDim::HistItem Hist = Handler->GetHistory(Service);
    2626  char *Name, *Fmt;
    2727
    2828  // Check if history service available
    2929  if (strcmp(Service, "Edd/Rate_kBSec") == 0) Format = "F";
    30   else if (Hist == NULL || Hist->GetFormat() == NULL) {
    31         printf("Edd Message: Could not retrieve history for service %s\n", Service);
    32   }
    33   else Format = Hist->GetFormat();
     30  else Format = Hist.Format;
    3431 
    3532  // If service currently available, take its format
     
    3734  if (Browser.getNextService(Name, Fmt) != 0) Format = QString(Fmt);
    3835
    39   Handler->DropHistory(Service);
    40  
    4136  // Open new window   
    4237  QMainWindow *M = new QMainWindow;
     
    5146  else  {
    5247    EddPlot *W = new EddPlot(Service, FromIndex);
    53         for (int i=FromIndex+1; i<=ToIndex; i++) {
    54           W->AddService(Service,i);
    55       Layout->addWidget(new EddLineDisplay(Service, i), 1 + (i-FromIndex)/5, (i-FromIndex)%5);
    56         }
     48        for (int i=FromIndex+1; i<=ToIndex; i++) W->AddService(Service,i);
     49 
    5750        Layout->addWidget(W, 0, 0, 1, 5);
    5851  }
    5952 
    60   Layout->addWidget(new EddLineDisplay(Service, FromIndex), 1, 0);
    6153  M->resize(400,450);
    6254  M->show();
     
    7062  QString Status;
    7163
    72   if (Index != -1) Name = Name + "[" + QString::number(Index) + "]";
     64  if (Index != -1) Name = Name + ":" + QString::number(Index);
    7365
    7466  if (Time == -1) Status = QString("%1:  unavailable").arg(Name);
     
    332324  connect(axisWidget(QwtPlot::xBottom), SIGNAL(scaleDivChanged()), SLOT(update()));
    333325
    334   legend()->setItemMode(QwtLegend::ClickableItem);
    335   connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
    336  
    337326  // Additonal context menu items
    338327  QAction* Action = Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
     
    344333  Action = Menu->addAction("Show last day", this, SLOT(MenuShowLastDay()));
    345334  Menu->insertAction(Menu->actions().value(8), Action); 
     335
     336  Action = Menu->addAction("All as text", this, SLOT(MenuAllAsText()));
     337  Menu->insertAction(Menu->actions().value(10), Action);
    346338   
    347339  // Set timer to regularly update plot if new data available
     
    357349EddPlot::~EddPlot() {
    358350
    359   while (!List.isEmpty()) DeleteCurve(List.last().Signal);
    360 }
    361 
    362 // Add history service to plot
     351  while (!List.isEmpty()) RemoveService(List.last().Curve);
     352}
     353
     354// Add service to plot
    363355void EddPlot::AddService(QString Name, int Index) {
    364356
     
    375367
    376368  N.Name = Name;
    377   N.Signal = NewCurve(Name+"["+QString::number(Index)+"]");
    378369  N.Index = Index;
     370  N.Curve = NewCurve(Name+":"+QString::number(Index));
    379371  List.append(N);
    380372
    381   // Request new history buffer
    382   const struct EvidenceHistory::Item *R;
    383   class EvidenceHistory *Hist;
    384 
    385   if ((Hist = Handler->GetHistory(Name)) != NULL) {
    386         double Number=0;
    387         while ((R=Hist->Next()) != NULL) {
    388           std::vector<std::string> Data = EvidenceServer::Tokenize(EvidenceServer::ToString(Hist->GetFormat(), R->Data, R->Size));
    389           if (N.Index > 0 && N.Index < (int) Data.size()) Number = atof(Data[N.Index].c_str());
    390           AddPoint(List.size()-1, R->Time, Number);
    391         }
    392   }
    393   Handler->DropHistory(Name);
     373  // Use custom legend widget
     374  EddLegend *Legend = new EddLegend(N.Curve, this);
     375  legend()->remove(N.Curve);
     376  legend()->insert(N.Curve, (QWidget *) Legend);
     377 
     378  // Context menu might delete curve and legend -> seg fault if using direct connection, as legend item deleted
     379  connect(Legend, SIGNAL(DeleteCurve(QwtPlotCurve *)), this, SLOT(RemoveService(QwtPlotCurve *)), Qt::QueuedConnection);
     380
     381  // Get history
     382  struct EddDim::HistItem Hist = Handler->GetHistory(Name);
     383
     384  for (int i=0; i<Hist.DataText.size(); i++) {
     385        AddPoint(List.size()-1, Hist.DataText[i].first, Hist.DataText[i].second.at(N.Index).toFloat());
     386  }
     387
     388  // Subscribe to service and start updating plot after 100 ms (to allow addition of other curves)
    394389  Handler->Subscribe(Name, this, Index);
    395  
    396390  SingleShot->start(100);
    397391}
     
    407401  }
    408402}
    409 
    410403
    411404// Add text indicating time range to plot
     
    435428}
    436429
    437 void EddPlot::LegendClicked(QwtPlotItem *Item) {
    438 
    439   QString D(Item->title().text());
    440   D.replace('(',' ').chop(1);
    441  
    442   QDrag *Drag = new QDrag(this);
    443   QMimeData *MimeData = new QMimeData;
    444   QByteArray Data;
    445   MimeData->setData("Edd/Service", Data.append(D));
    446   Drag->setMimeData(MimeData);
    447   Drag->exec();
    448 }
    449 
    450430// Add new service by pasting name
    451431void EddPlot::MenuPasteService() {
     
    462442
    463443  setAxisScale(QwtPlot::xBottom, time(NULL)-60*60, time(NULL)+60);
    464   //setAxisAutoScale(QwtPlot::yLeft);
    465444  replot();
    466445}
     
    469448
    470449  setAxisScale(QwtPlot::xBottom, time(NULL)-24*3600, time(NULL)+3600);
    471   //setAxisAutoScale(QwtPlot::yLeft);
    472450  replot();
    473451}
    474452
    475 
    476 // Remove list entry
    477 void EddPlot::DeleteCurve(QwtPlotCurve *Curve) {
    478 
    479   for (int i=0; i<List.size(); i++) if (List[i].Signal == Curve) {
    480     Handler->Unsubscribe(List[i].Name, this, List[i].Index);
    481     List.removeAt(i);
    482   }
     453void EddPlot::MenuAllAsText() {
     454
     455  QMainWindow *M = new QMainWindow;
     456  M->setCentralWidget(new QWidget(M));
     457  M->setStatusBar(new QStatusBar(M));
     458  M->setAttribute(Qt::WA_DeleteOnClose);
     459  M->setWindowTitle("Edd Services");
     460
     461  QGridLayout *Layout = new QGridLayout(M->centralWidget());
     462
     463  for (int i=0; i<List.size(); i++) {
     464      Layout->addWidget(new EddLineDisplay(List[i].Name, List[i].Index), i/10, i%10);
     465  }
     466
     467  M->resize(400,450);
     468  M->show();
     469}
     470
     471
     472// Remove subscription
     473void EddPlot::RemoveService(QwtPlotCurve *Curve) {
     474
     475  for (int i=0; i<List.size(); i++) if (List[i].Curve == Curve) {
     476        Handler->Unsubscribe(List[i].Name, this, List[i].Index);
     477        List.removeAt(i);
     478        DeleteCurve(Curve);
     479        break;
     480  } 
    483481}
    484482
     
    543541  StatisticsAction->setCheckable(true);
    544542  Menu->addAction("Zoom out", this, SLOT(MenuZoomOut()));
    545   Menu->addAction("Single trace", this, SLOT(MenuSingleTrace()));
    546543  Menu->addSeparator();
    547544  Menu->addAction("Set update rate", this, SLOT(MenuSetUpdateRate())); 
     
    561558EddBasePlot::~EddBasePlot() {
    562559
    563   for (int i=0; i<Items.size(); i++) delete Items[i].Signal;
    564560  delete Grid;
    565561}
     
    739735  // Selection region outside all axis?
    740736  if (R.right() < 0 && R.top() > plotLayout()->canvasRect().height()) return;
     737
     738  // If selected rectangle completely inside canvas taken care of by zoomer
     739  if (plotLayout()->canvasRect().contains(P.boundingRect())) return;
    741740 
    742741  // Rescale both axis if selected rectangle encompasses canvas completely
     
    803802}
    804803
    805 // Remove all items except one
    806 void EddBasePlot::MenuSingleTrace() {
    807 
    808   while (Items.size() > 1) { 
    809         DeleteCurve(Items.last().Signal);
    810     delete Items.last().Signal;
    811     Items.takeLast();
     804
     805// Remove item
     806void EddBasePlot::DeleteCurve(QwtPlotCurve *Curve) {
     807
     808  for (int i=0; i<Items.size(); i++) if (Items[i].Signal == Curve) {
     809        delete Curve;
     810        Items.takeAt(i);
     811        break;
    812812  }
    813813  UpdatePlot();
     
    893893}
    894894
     895
     896////////////////
     897// Edd Legend //
     898////////////////
     899
     900EddLegend::EddLegend(QwtPlotCurve *Curve, EddPlot *Plot): Curve(Curve), Plot(Plot) {
     901
     902  // Context menu
     903  Menu = new QMenu(this);
     904  Menu->addAction("Open in new history", this, SLOT(MenuOpenHistory()));
     905  Menu->addAction("Copy service", this, SLOT(MenuCopyService()));
     906  Menu->addAction("Normal line", this, SLOT(MenuNormalLine()));
     907  Menu->addAction("Thick line", this, SLOT(MenuThickLine()));
     908  Menu->addAction("Remove curve", this, SLOT(MenuRemove()));
     909}
     910
     911//
     912// Opening context menu
     913//
     914void EddLegend::contextMenuEvent(QContextMenuEvent *Event) {
     915 
     916  Menu->exec(Event->globalPos());
     917}
     918
     919// Handling of mouse press event: Register start position for drag
     920void EddLegend::mousePressEvent(QMouseEvent *Event) {
     921
     922  if (Event->button() == Qt::LeftButton) dragStart = Event->pos();
     923}
     924
     925// Handling of dragging (Drag and MimeData will be deleted by Qt)
     926void EddLegend::mouseMoveEvent(QMouseEvent *Event) {
     927
     928  if ((Event->buttons() & Qt::LeftButton) == 0) return;
     929  if ((Event->pos()-dragStart).manhattanLength() < QApplication::startDragDistance()) return;
     930
     931  QString D(text().text());
     932  D.replace(':',' ');
     933
     934  QDrag *Drag = new QDrag(this);
     935  QMimeData *MimeData = new QMimeData;
     936  QByteArray Data;
     937  MimeData->setData("Edd/Service", Data.append(D));
     938  Drag->setMimeData(MimeData);
     939  Drag->exec();
     940}
     941
     942// Handling of mouse release event: Open history
     943void EddLegend::mouseReleaseEvent(QMouseEvent *Event) {
     944
     945  if (Event->button() != Qt::LeftButton) return;
     946 
     947  QString D(text().text());
     948  D.replace(':',' ');
     949  QStringList A = D.split(" ");
     950 
     951  OpenHistory(A[0].toAscii().data(), A[1].toInt());
     952}
     953
     954// Menu: Open history plot
     955void EddLegend::MenuOpenHistory() {
     956
     957  QString D(text().text());
     958  D.replace(':',' ');
     959  QStringList A = D.split(" ");
     960 
     961  OpenHistory(A[0].toAscii().data(), A[1].toInt());
     962}
     963
     964// Menu: Copy service name
     965void EddLegend::MenuCopyService() {
     966
     967  QString D(text().text());
     968  D.replace(':',' ');
     969 
     970  QMimeData *MimeData = new QMimeData;
     971  QByteArray Data;
     972  MimeData->setData("Edd/Service", Data.append(D));
     973  QApplication::clipboard()->setMimeData(MimeData);
     974}
     975
     976// Menu: Normal line width
     977void EddLegend::MenuNormalLine() {
     978
     979  QPen Pen = Curve->pen();
     980  Pen.setWidth(1);
     981  Curve->setPen(Pen);
     982  Curve->plot()->replot();
     983}
     984
     985// Menu: Normal line width
     986void EddLegend::MenuThickLine() {
     987
     988  QPen Pen = Curve->pen();
     989  Pen.setWidth(4);
     990  Curve->setPen(Pen);
     991  Curve->plot()->replot();
     992}
     993
     994// Menu: Normal line width
     995void EddLegend::MenuRemove() {
     996
     997  emit(DeleteCurve(Curve));
     998}
     999
    8951000//////////////////////////////////////
    8961001// History text box for DIM service //
     
    9051010  setAttribute(Qt::WA_DeleteOnClose);
    9061011  setAutoFillBackground(true);
    907   setText("connecting...");
     1012  //setText("connecting...");
    9081013  document()->setMaximumBlockCount(1000);
    9091014  Accumulate = true;
    9101015 
     1016  // Get history for this service
    9111017  if (!Pure) {
    912         // Get history for this service
    913         const struct EvidenceHistory::Item *R;
    914         class EvidenceHistory *Hist;
    915 
    916         if ((Hist = Handler->GetHistory(Name)) != NULL) {
    917           while ((R=Hist->Next()) != NULL) {
    918                 moveCursor (QTextCursor::Start);
    919                 insertPlainText(QString("(")+QDateTime::fromTime_t(R->Time).toString()+") " +
    920                   QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), (void *) R->Data, R->Size)) + "\n");
    921           }     
    922         }
    923         Handler->DropHistory(Name);
     1018        struct EddDim::HistItem Hist = Handler->GetHistory(Name);
     1019       
     1020        for (int i=0; i<Hist.DataText.size(); i++) {
     1021          moveCursor (QTextCursor::Start);
     1022          insertPlainText(QString("(")+QDateTime::fromTime_t(Hist.DataText[i].first).toString()+") " +
     1023                  QString(Hist.DataRaw[i].second) + "\n");
     1024        }       
    9241025  }
    9251026
     
    9871088EddDim::~EddDim() {
    9881089
    989   QList<QString> L = HistoryList.keys();
    990   for(int i=0; i<L.size(); i++) delete HistoryList[L[i]].HistClass;
    9911090  delete Mutex;
    9921091}
     
    10431142
    10441143  QMutexLocker Locker(&IgnoreMutex);
    1045 
    10461144  IgnoreMap[Name] = Ignore;
    10471145}
    10481146
    10491147// Get history buffer
    1050 class EvidenceHistory *EddDim::GetHistory(QString Name) {
    1051 
    1052   // History already available (only request again if too old)
    1053   if (HistoryList.contains(Name)) {
    1054         HistoryList[Name].Count++;
    1055 
    1056         if (time(NULL)-HistoryList[Name].LastUpdate < 5) {
    1057           HistoryList[Name].HistClass->Rewind();
    1058           return HistoryList[Name].HistClass;
    1059         }
    1060         HistoryList[Name].LastUpdate = time(NULL);
    1061         if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
    1062         else return NULL;
    1063   }
    1064 
    1065   // Create new history class
    1066   HistoryList[Name].HistClass = new EvidenceHistory(Name.toStdString());
    1067   HistoryList[Name].Count = 1;
    1068   HistoryList[Name].LastUpdate = time(NULL);
    1069 
    1070   if (HistoryList[Name].HistClass->GetHistory()) return HistoryList[Name].HistClass;
    1071   else return NULL;
    1072 }
    1073 
    1074 // Reduce history usage counter
    1075 void EddDim::DropHistory(QString Name) {
    1076 
    1077   if (HistoryList.contains(Name)) HistoryList[Name].Count--;
    1078 }
     1148struct EddDim::HistItem EddDim::GetHistory(QString Name) {
     1149
     1150  // History already available?
     1151  if (HistoryList.contains(Name)) return HistoryList[Name];
     1152
     1153  // Create history class to retrieve history data
     1154  const struct EvidenceHistory::Item *R;
     1155  class EvidenceHistory *Hist  = new EvidenceHistory(Name.toStdString());
     1156  Hist->GetHistory();
     1157  HistoryList[Name].Time = time(NULL);
     1158  HistoryList[Name].Format = Hist->GetFormat();
     1159
     1160  while ((R = Hist->Next()) != NULL) {
     1161        HistoryList[Name].DataRaw.push_back(QPair<int, QByteArray>(R->Time, QByteArray(R->Data, R->Size)));
     1162        HistoryList[Name].DataText.push_back(QPair<int, QStringList>(R->Time, QString::fromStdString(EvidenceServer::ToString(Hist->GetFormat(), R->Data, R->Size)).split(' ')));
     1163  }
     1164 
     1165  delete Hist;
     1166
     1167  return HistoryList[Name];
     1168}
     1169
    10791170
    10801171// Update throughput statistics and clear up history memory
     
    10871178  QList<QString> L = HistoryList.keys();
    10881179  for(int i=0; i<L.size(); i++) {
    1089         if ((HistoryList[L[i]].Count <= 0) && (time(NULL)-HistoryList[L[i]].LastUpdate) > 5) {
    1090           delete HistoryList[L[i]].HistClass;
    1091           HistoryList.remove(L[i]);
    1092         }
     1180        if ((time(NULL)-HistoryList[L[i]].Time) > 60) HistoryList.remove(L[i]);
    10931181  }
    10941182 
  • fact/Evidence/GUI.h

    r12894 r12940  
    1111#include <qwt_plot_magnifier.h>
    1212#include <qwt_plot_panner.h>
     13#include <qwt_picker_machine.h>
    1314#include <qwt_scale_engine.h>
    1415#include <qwt_analog_clock.h>
     
    4041        virtual void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int=-1) = 0;
    4142};
     43
    4244
    4345// Base class for Edd plot
     
    8284        bool NewData;
    8385        QwtPlotCurve *NewCurve(QwtText);
     86        void DeleteCurve(QwtPlotCurve *);
    8487        void ClearCurve(unsigned int);
    8588        void AddPoint(unsigned int, double, double);
    86         virtual void DeleteCurve(QwtPlotCurve *) = 0;
    8789
    8890  protected slots:
     
    9496        void MouseSelection(const QwtPolygon &);
    9597        void contextMenuEvent(QContextMenuEvent *);
    96     void MenuSingleTrace();       
    9798    void MenuSetUpdateRate();       
    9899    void MenuZoomOut();
     
    180181      QString Name;
    181182          int Index;
    182       QwtPlotCurve *Signal;       
     183          QwtPlotCurve *Curve;
    183184    };
    184185    QList<struct ItemDetails> List;
     
    187188        QwtLegend *Legend;
    188189        QTimer *SingleShot;
     190    QPoint dragStart;
    189191
    190192    void dragEnterEvent(QDragEnterEvent *);
     
    196198    ~EddPlot();
    197199    void AddService(QString, int = 0);
    198         void DeleteCurve(QwtPlotCurve *);
    199200        void Update(const QString &, int, const QByteArray &, const QString &, const QString &, int = -1);
    200201
    201   private slots:
    202         void LegendClicked(QwtPlotItem *);
     202  public slots:
     203        void RemoveService(QwtPlotCurve *);
     204
     205  private slots:
    203206    void MenuPasteService();
    204207        void MenuShowLastHour();
    205208        void MenuShowLastDay();
    206 };
    207 
     209        void MenuAllAsText();
     210};
     211
     212
     213// Legend
     214class EddLegend: public QwtLegendItem {
     215    Q_OBJECT
     216
     217    QMenu *Menu;
     218    QPoint dragStart;
     219        QwtPlotCurve *Curve;
     220        EddPlot *Plot;
     221
     222  public:
     223        EddLegend(QwtPlotCurve *, EddPlot *);
     224
     225        void contextMenuEvent(QContextMenuEvent *);
     226        void mousePressEvent(QMouseEvent *);
     227        void mouseReleaseEvent(QMouseEvent *);
     228    void mouseMoveEvent(QMouseEvent *);
     229       
     230  private slots:
     231        void MenuOpenHistory();
     232        void MenuCopyService();
     233        void MenuNormalLine();
     234        void MenuThickLine();
     235        void MenuRemove();
     236       
     237  signals:
     238        void DeleteCurve(QwtPlotCurve *);
     239};
    208240
    209241// Text history and output class
     
    227259class EddDim: public QObject, public DimInfo {
    228260  Q_OBJECT
     261
     262  public:
     263        struct HistItem {
     264          int Time;
     265          QVector<QPair<int, QByteArray> > DataRaw;
     266          QVector<QPair<int, QStringList> > DataText;
     267          QString Format;
     268        };
    229269
    230270  private:
     
    238278          QStringList Items;
    239279        };
     280
    240281    QMap<QString, struct Item> ServiceList;
    241282        QMap<QString, bool> IgnoreMap;
    242283    QMutex *Mutex, IgnoreMutex;
    243 
    244         struct HistItem {
    245           int Count;
    246           int LastUpdate;
    247           class EvidenceHistory *HistClass;
    248         };
    249284    QMap<QString, struct HistItem> HistoryList;
    250285
     
    265300        void Unsubscribe (QString, class EddWidget *, int = -1);
    266301        void Ignore (QString, bool);
    267         class EvidenceHistory *GetHistory(QString);
    268         void DropHistory(QString);
     302        struct HistItem GetHistory(QString);
    269303
    270304  signals:
  • fact/Evidence/History.cc

    r12910 r12940  
    5252       
    5353        DimInfo *ServerList;
     54        DimService *Service;
    5455        char *Directory;
    5556
     
    7273                                                         EvidenceServer(SERVER_NAME),
    7374                                                         Directory(Dir) {
    74 
    7575  // Get/initialize configuration
    7676  GetConfig("minchange", " ");
     
    8080  GetConfig("exclude", "");
    8181
     82  // Create services for information about subscribed services
     83  Service = new DimService(SERVER_NAME "/Subscriptions", "C", NULL, 0);
     84
    8285  // Subscribe to top-level server list
    8386  ServerList = new DimInfo((char *) "DIS_DNS/SERVER_LIST", NO_LINK, this);
     
    9093  delete ServerList;
    9194  while (Map.size() != 0) RemoveService((*Map.begin()).first);
     95 
     96  delete Service;
    9297}
    9398
     
    96101void History::infoHandler() {
    97102
     103  static string List;
     104
    98105  DimInfo *I = getInfo();
    99106
    100107  // Check if service available
    101108  if (!ServiceOK(I)) return;
    102  
     109
    103110  // ====== Part A: Handle service subscriptions ===
    104111 
     
    138145          Name = strtok(NULL, "|");
    139146        }
     147       
     148        // Update service subscription list
     149        static stringstream Stream;
     150       
     151        for (map<string, struct Item>::const_iterator i=Map.begin(); i!=Map.end(); i++) {
     152          Stream << i->first << ':' << i->second.MinAbsChange << '|';
     153        }
     154        List = Stream.str();
     155        Service->updateService((void *) List.c_str(), List.size()+1);
     156       
    140157        return;
    141158  }
  • fact/Evidence/readme.txt

    r12910 r12940  
    6161                        value of indices a to b)
    626220/2/2012       Disabled padding per default in Evidence class constructor, and also in History and DColl
    63                         servers. EvidenceServer::ToString() can because of this now handle all format strings.
     63                        servers. EvidenceServer::ToString() can because of this now handle all format strings.
     6424/2/2012   Improved interactive behaviour of legend items (drag&drop, context menu). Handling of histories in
     65                        Edd much faster now. Made a new version Edd:LP for La Palma. History server publishes a list of
     66                        services subscribed to.
Note: See TracChangeset for help on using the changeset viewer.