File indexing completed on 2024-12-22 04:17:55

0001 /***************************************************************************
0002  *                                                                         *
0003  *   copyright : (C) 2007 The University of Toronto                        *
0004  *                   netterfield@astro.utoronto.ca                         *
0005  *   copyright : (C) 2004 University of British Columbia                  *
0006  *                   dscott@phas.ubc.ca                                    *
0007  *                                                                         *
0008  *   This program is free software; you can redistribute it and/or modify  *
0009  *   it under the terms of the GNU General Public License as published by  *
0010  *   the Free Software Foundation; either version 2 of the License, or     *
0011  *   (at your option) any later version.                                   *
0012  *                                                                         *
0013  ***************************************************************************/
0014 
0015 #include <config.h>
0016 
0017 #include "eventmonitorentry.h"
0018 
0019 // include files for Qt
0020 #include <qthread.h>
0021 #include <QEvent>
0022 #include <QApplication>
0023 
0024 // application specific includes
0025 #include "enodes.h"
0026 #include "dialoglauncher.h"
0027 #include "datacollection.h"
0028 
0029 #include <QXmlStreamWriter>
0030 
0031 #include "debug.h"
0032 
0033 #include <assert.h>
0034 #ifndef Q_OS_WIN32
0035 #include <unistd.h>
0036 #endif
0037 
0038 extern int yyparse(Kst::ObjectStore *store);
0039 extern void *ParsedEquation;
0040 extern struct yy_buffer_state *yy_scan_string(const char*);
0041 
0042 namespace Kst {
0043 
0044 const QString EventMonitorEntry::staticTypeString = "Event Monitor";
0045 const QString EventMonitorEntry::staticTypeTag = "eventmonitor";
0046 
0047 namespace {
0048   const int EventMonitorEventType = int(QEvent::User) + 2931;
0049   class EventMonitorEvent : public QEvent {
0050     public:
0051       EventMonitorEvent(const QString& msg) : QEvent(QEvent::Type(EventMonitorEventType)), logMessage(msg) {}
0052       QString logMessage;
0053   };
0054 }
0055 
0056 //extern "C" int yyparse();
0057 //extern "C" void *ParsedEquation;
0058 //extern "C" struct yy_buffer_state *yy_scan_string(const char*);
0059 
0060 const QString EventMonitorEntry::OUTXVECTOR('X');
0061 const QString EventMonitorEntry::OUTYVECTOR('Y');
0062 
0063 EventMonitorEntry::EventMonitorEntry(ObjectStore *store) : DataObject(store) {
0064   _level = Debug::Warning;
0065   _logDebug = true;
0066   _logEMail = false;
0067   _logELOG = false;
0068 
0069   const int NS = 1;
0070 
0071   _numDone = 0;
0072   _isValid = false;
0073   _pExpression = 0L;
0074 
0075   _typeString = staticTypeString;
0076   _type = "Event";
0077   _initializeShortName();
0078 
0079   VectorPtr xv = store->createObject<Vector>();
0080   xv->resize(NS);
0081   xv->setProvider(this);
0082   _xVector = _outputVectors.insert(OUTXVECTOR, xv);
0083 
0084   VectorPtr yv = store->createObject<Vector>();
0085   yv->resize(NS);
0086   yv->setProvider(this);
0087   _yVector = _outputVectors.insert(OUTYVECTOR, yv);
0088 }
0089 
0090 void EventMonitorEntry::_initializeShortName() {
0091 }
0092 
0093 bool EventMonitorEntry::reparse() {
0094   _isValid = false;
0095   if (!_event.isEmpty()) {
0096     Equations::mutex().lock();
0097     yy_scan_string(_event.toLatin1());
0098     int rc = yyparse(store());
0099     if (rc == 0) {
0100       _pExpression = static_cast<Equations::Node*>(ParsedEquation);
0101       Equations::Context ctx;
0102       Equations::FoldVisitor vis(&ctx, &_pExpression);
0103       StringMap stm;
0104       _pExpression->collectObjects(_vectorsUsed, _inputScalars, stm);
0105 
0106       for (ScalarMap::ConstIterator i = _inputScalars.constBegin(); i != _inputScalars.constEnd(); ++i) {
0107         if ((*i)->myLockStatus() == KstRWLock::UNLOCKED) {
0108           (*i)->readLock();
0109         }
0110       }
0111       Equations::mutex().unlock();
0112       _isValid = true;
0113     } else {
0114       delete (Equations::Node*)ParsedEquation;
0115       Equations::mutex().unlock();
0116     }
0117     ParsedEquation = 0L;
0118   }
0119   return _isValid;
0120 }
0121 
0122 
0123 void EventMonitorEntry::save(QXmlStreamWriter &xml) {
0124   xml.writeStartElement(staticTypeTag);
0125   xml.writeAttribute("equation", _event);
0126   xml.writeAttribute("description", _description);
0127   xml.writeAttribute("logdebug", QVariant(_logDebug).toString());
0128   xml.writeAttribute("loglevel", QVariant(_level).toString());
0129   xml.writeAttribute("logemail", QVariant(_logEMail).toString());
0130   xml.writeAttribute("logelog", QVariant(_logELOG).toString());
0131   xml.writeAttribute("emailrecipients", _eMailRecipients);
0132   xml.writeAttribute("script", _script);
0133   xml.writeEndElement();
0134 }
0135 
0136 
0137 EventMonitorEntry::~EventMonitorEntry() {
0138   logImmediately(false);
0139 
0140   delete _pExpression;
0141   _pExpression = 0L;
0142 }
0143 
0144 
0145 void EventMonitorEntry::internalUpdate() {
0146   writeLockInputsAndOutputs();
0147 
0148   if (!_pExpression) {
0149     reparse();
0150   }
0151 
0152   VectorPtr xv = *_xVector;
0153   VectorPtr yv = *_yVector;
0154   int ns = 1;
0155 
0156   for (VectorMap::ConstIterator i = _vectorsUsed.constBegin(); i != _vectorsUsed.constEnd(); ++i) {
0157     ns = qMax(ns, i.value()->length());
0158   }
0159 
0160   double *rawValuesX = 0L;
0161   double *rawValuesY = 0L;
0162   if (xv && yv) {
0163     if (xv->resize(ns)) {
0164       rawValuesX = xv->raw_V_ptr();
0165     }
0166 
0167     if (yv->resize(ns)) {
0168       rawValuesY = yv->raw_V_ptr();
0169     }
0170   }
0171 
0172   Equations::Context ctx;
0173   ctx.sampleCount = ns;
0174   ctx.x = 0.0;
0175 
0176   if (needToEvaluate()) {
0177     if (_pExpression) {
0178       for (ctx.i = _numDone; ctx.i < ns; ++ctx.i) {
0179         const double value = _pExpression->value(&ctx);
0180         if (value != 0.0) { // The expression evaluates to true
0181           log(ctx.i);
0182           if (rawValuesX && rawValuesY) {
0183             rawValuesX[ctx.i] = ctx.i;
0184             rawValuesY[ctx.i] = 1.0;
0185           }
0186         } else {
0187           if (rawValuesX && rawValuesY) {
0188             rawValuesX[ctx.i] = ctx.i;
0189             rawValuesY[ctx.i] = 0.0;
0190           }
0191         }
0192       }
0193       _numDone = ns;
0194       logImmediately();
0195     }
0196   } else {
0197     _numDone = ns;
0198   }
0199 
0200   unlockInputsAndOutputs();
0201 
0202   return;
0203 }
0204 
0205 
0206 void EventMonitorEntry::setEvent(const QString& strEvent) {
0207   if (_event != strEvent) {
0208     _event = strEvent;
0209     _vectorsUsed.clear();
0210     _inputScalars.clear();
0211 
0212     _numDone = 0;
0213     _isValid = false;
0214 
0215     delete _pExpression;
0216     _pExpression = 0L;
0217   }
0218 }
0219 
0220 
0221 bool EventMonitorEntry::needToEvaluate() {
0222   return _logDebug || _logEMail || _logELOG || !_script.isEmpty();
0223 }
0224 
0225 
0226 void EventMonitorEntry::logImmediately(bool sendEvent) {
0227   const int arraySize = _indexArray.size();
0228 
0229   if (arraySize > 0) {
0230     QString logMessage;
0231     QString rangeString;
0232     bool makeRange = false;
0233     int idx = 0;
0234     int idxOld = 0;
0235 
0236     for (int i = 0; i < arraySize; ++i) {
0237       idx = _indexArray.at(i);
0238       if (i == 0) {
0239         rangeString.setNum(idx);
0240       } else if (!makeRange && idx == idxOld + 1) {
0241         makeRange = true;
0242       } else if (makeRange && idx != idxOld + 1) {
0243         rangeString = rangeString + QString(" - %1, %2").arg(idxOld).arg(idx);
0244         makeRange = false;
0245       } else if (idx != idxOld + 1) {
0246         rangeString = rangeString + QString(", %1").arg(idx);
0247       }
0248       idxOld = idx;
0249     }
0250 
0251     if (makeRange) {
0252         rangeString = rangeString + QString(", %1").arg(idx);
0253     }
0254 
0255     if (_description.isEmpty()) {
0256       logMessage = "Event Monitor: " + _event + ": " + rangeString;
0257     } else {
0258       logMessage = "Event Monitor: " + _description + ": " + rangeString;
0259     }
0260 
0261     _indexArray.clear();
0262 
0263     if (sendEvent) { // update thread
0264       QApplication::postEvent(this, new EventMonitorEvent(logMessage));
0265     } else { // GUI thread
0266       doLog(logMessage);
0267     }
0268   }
0269 }
0270 
0271 
0272 bool EventMonitorEntry::event(QEvent *e) {
0273     if (e->type() == EventMonitorEventType) {
0274       readLock();
0275       doLog(static_cast<EventMonitorEvent*>(e)->logMessage);
0276       unlock();
0277       return true;
0278     }
0279     return false;
0280 }
0281 
0282 
0283 void EventMonitorEntry::doLog(const QString& logMessage) const {
0284   if (_logDebug) {
0285     Debug::self()->log(logMessage, _level);
0286   }
0287 
0288   //if (_logEMail && !_eMailRecipients.isEmpty()) {
0289   //  EMailThread* thread = new EMailThread(_eMailRecipients, "Kst Event Monitoring Notification", logMessage);
0290   //  thread->send();
0291   //}
0292 
0293 //FIXME ELOG need to be implemented.
0294 //   if (_logELOG) {
0295 //     KstApp::inst()->EventELOGSubmitEntry(logMessage);
0296 //   }
0297 
0298 //FIXME PORT!
0299 //   if (!_script.isEmpty()) {
0300 //     DCOPRef ref(QString("kst-%1").arg(getpid()).toLatin1(), "KstScript");
0301 //     ref.send("evaluate", _script);
0302 //   }
0303 }
0304 
0305 
0306 void EventMonitorEntry::log(int idx) {
0307   _indexArray.append(idx);
0308   if (_indexArray.size() > 1000) {
0309     logImmediately();
0310   }
0311 }
0312 
0313 
0314 QString EventMonitorEntry::propertyString() const {
0315   return _event;
0316 }
0317 
0318 
0319 void EventMonitorEntry::showNewDialog() {
0320   DialogLauncher::self()->showEventMonitorDialog();
0321 }
0322 
0323 
0324 void EventMonitorEntry::showEditDialog() {
0325   DialogLauncher::self()->showEventMonitorDialog();
0326 }
0327 
0328 
0329 const QString& EventMonitorEntry::scriptCode() const {
0330   return _script;
0331 }
0332 
0333 
0334 void EventMonitorEntry::setScriptCode(const QString& script) {
0335   if (_script != script) {
0336     _script = script;
0337   }
0338 }
0339 
0340 
0341 void EventMonitorEntry::setDescription(const QString& str) {
0342   if (_description != str) {
0343     _description = str;
0344   }
0345 }
0346 
0347 
0348 void EventMonitorEntry::setLevel(Debug::LogLevel level) {
0349   if (_level != level) {
0350     _level = level;
0351   }
0352 }
0353 
0354 
0355 void EventMonitorEntry::setExpression(Equations::Node* pExpression) {
0356   if (_pExpression != pExpression) {
0357     _pExpression = pExpression;
0358   }
0359 }
0360 
0361 
0362 void EventMonitorEntry::setLogDebug(bool logDebug) {
0363   if (_logDebug != logDebug) {
0364     _logDebug = logDebug;
0365   }
0366 }
0367 
0368 
0369 void EventMonitorEntry::setLogEMail(bool logEMail) {
0370   if (logEMail != _logEMail) {
0371     _logEMail = logEMail;
0372   }
0373 }
0374 
0375 
0376 void EventMonitorEntry::setLogELOG(bool logELOG) {
0377   if (logELOG != _logELOG) {
0378     _logELOG = logELOG;
0379   }
0380 }
0381 
0382 
0383 void EventMonitorEntry::setEMailRecipients(const QString& str) {
0384   if (str != _eMailRecipients) {
0385     _eMailRecipients = str;
0386   }
0387 }
0388 
0389 
0390 DataObjectPtr EventMonitorEntry::makeDuplicate() const {
0391   EventMonitorEntryPtr eventMonitor = store()->createObject<EventMonitorEntry>();
0392 
0393   eventMonitor->setScriptCode(_script);
0394   eventMonitor->setEvent(_event);
0395   eventMonitor->setDescription(_description);
0396   eventMonitor->setLevel(_level);
0397   eventMonitor->setLogDebug(_logDebug);
0398   eventMonitor->setLogEMail(_logEMail);
0399   eventMonitor->setLogELOG(_logELOG);
0400   eventMonitor->setEMailRecipients(_eMailRecipients);
0401 
0402   if (descriptiveNameIsManual()) {
0403     eventMonitor->setDescriptiveName(descriptiveName());
0404   }
0405   eventMonitor->reparse();
0406 
0407   eventMonitor->writeLock();
0408   eventMonitor->registerChange();
0409   eventMonitor->unlock();
0410 
0411   return DataObjectPtr(eventMonitor);
0412 }
0413 
0414 
0415 bool EventMonitorEntry::uses(ObjectPtr p) const {
0416   // check VectorsUsed in addition to _input*'s
0417   if (VectorPtr vect = kst_cast<Vector>(p)) {
0418     for (VectorMap::ConstIterator j = _vectorsUsed.begin(); j != _vectorsUsed.end(); ++j) {
0419       if (j.value() == vect) {
0420         return true;
0421       }
0422     }
0423   } else if (DataObjectPtr obj = kst_cast<DataObject>(p) ) {
0424     // check all connections from this expression to p
0425     for (VectorMap::ConstIterator j = obj->outputVectors().constBegin(); j != obj->outputVectors().constEnd(); ++j) {
0426       for (VectorMap::ConstIterator k = _vectorsUsed.constBegin(); k != _vectorsUsed.constEnd(); ++k) {
0427         if (j.value() == k.value()) {
0428           return true;
0429         }
0430       }
0431     }
0432   }
0433   return DataObject::uses(p);
0434 }
0435 
0436 QString EventMonitorEntry::_automaticDescriptiveName() const {
0437   return tr("event");
0438 }
0439 
0440 QString EventMonitorEntry::descriptionTip() const {
0441   return tr("Event: %1").arg(Name());
0442 }
0443 
0444 }
0445 
0446 // vim: ts=2 sw=2 et