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