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

0001 /***************************************************************************
0002                   dataobject.cpp: base class for data objects
0003                              -------------------
0004     begin                : May 20, 2003
0005     copyright            : (C) 2003 by C. Barth Netterfield
0006     email                : netterfield@astro.utoronto.ca
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  ***************************************************************************/
0017 
0018 #include "dataobject.h"
0019 
0020 #include "datacollection.h"
0021 #include "dataobjectplugin.h"
0022 #include "debug.h"
0023 
0024 #include "objectstore.h"
0025 #include "relation.h"
0026 #include "sharedptr.h"
0027 #include "primitive.h"
0028 #include "settings.h"
0029 
0030 #include "dataobjectscriptinterface.h"
0031 
0032 #include <QApplication>
0033 #include <QDir>
0034 #include <qdebug.h>
0035 #include <qtimer.h>
0036 #include <QPluginLoader>
0037 #include <QLibraryInfo>
0038 #include <QXmlStreamReader>
0039 #include <QXmlStreamWriter>
0040 #include <limits.h>
0041 #include <assert.h>
0042 
0043 //#define LOCKTRACE
0044 
0045 using namespace Kst;
0046 
0047 
0048 QSettings& DataObject::settingsObject()
0049 {
0050   static QSettings& settingsObject = createSettings("data");
0051   return settingsObject;
0052 }
0053 
0054 QMap<QString,QString> DataObject::url_map;
0055 
0056 
0057 
0058 
0059 void DataObject::init() {
0060   initPlugins();
0061 }
0062 
0063 
0064 DataObject::DataObject(ObjectStore *store) : Object() {
0065   Q_UNUSED(store);
0066   _curveHints = new CurveHintList;
0067 }
0068 
0069 
0070 DataObject::~DataObject() {
0071   delete _curveHints;
0072 }
0073 
0074 
0075 static DataObjectPluginList _pluginList;
0076 void DataObject::cleanupForExit() {
0077   _pluginList.clear(); //FIXME?
0078 }
0079 
0080 
0081 void DataObject::attach() {
0082 }
0083 
0084 void DataObject::replaceInput(PrimitivePtr p, PrimitivePtr new_p) {
0085   if (VectorPtr v = kst_cast<Vector>(p) ) {
0086     if (VectorPtr new_v = kst_cast<Vector>(new_p)) {
0087       for (VectorMap::Iterator j = _inputVectors.begin(); j != _inputVectors.end(); ++j) {
0088         if (j.value() == v) {
0089           _inputVectors[j.key()] = new_v;
0090         }
0091       }
0092     }
0093   } else if (MatrixPtr m = kst_cast<Matrix>(p) ) {
0094     if (MatrixPtr new_m = kst_cast<Matrix>(new_p)) {
0095       for (MatrixMap::Iterator j = _inputMatrices.begin(); j != _inputMatrices.end(); ++j) {
0096         if (j.value() == m) {
0097           _inputMatrices[j.key()] = new_m;
0098         }
0099       }
0100     }
0101   } else if (StringPtr s = kst_cast<String>(p) ) {
0102     if (StringPtr new_s = kst_cast<String>(new_p)) {
0103       for (StringMap::Iterator j = _inputStrings.begin(); j != _inputStrings.end(); ++j) {
0104         if (j.value() == s) {
0105           _inputStrings[j.key()] = new_s;
0106         }
0107       }
0108     }
0109   } else if (ScalarPtr s = kst_cast<Scalar>(p) ) {
0110     if (ScalarPtr new_s = kst_cast<Scalar>(new_p)) {
0111       for (ScalarMap::Iterator j = _inputScalars.begin(); j != _inputScalars.end(); ++j) {
0112         if (j.value() == s) {
0113           _inputScalars[j.key()] = new_s;
0114         }
0115       }
0116     }
0117   }
0118 }
0119 
0120 
0121 VectorPtr DataObject::outputVector(const QString& vector) const {
0122   VectorMap::ConstIterator i = _outputVectors.constFind(vector);
0123   if (i != _outputVectors.constEnd())
0124     return *i;
0125   else
0126     return 0;
0127 }
0128 
0129 
0130 ScalarPtr DataObject::outputScalar(const QString& scalar) const {
0131   ScalarMap::ConstIterator i = _outputScalars.constFind(scalar);
0132   if (i != _outputScalars.constEnd())
0133     return *i;
0134   else
0135     return 0;
0136 }
0137 
0138 
0139 StringPtr DataObject::outputString(const QString& string) const {
0140   StringMap::ConstIterator i = _outputStrings.constFind(string);
0141   if (i != _outputStrings.constEnd())
0142     return *i;
0143   else
0144     return 0;
0145 }
0146 
0147 
0148 void DataObject::setInputVector(const QString &type, VectorPtr ptr) {
0149   if (ptr) {
0150     _inputVectors[type] = ptr;
0151   } else {
0152     _inputVectors.remove(type);
0153   }
0154 }
0155 
0156 
0157 void DataObject::setInputScalar(const QString &type, ScalarPtr ptr) {
0158   if (ptr) {
0159     _inputScalars[type] = ptr;
0160   } else {
0161     _inputScalars.remove(type);
0162   }
0163 }
0164 
0165 
0166 void DataObject::setInputString(const QString &type, StringPtr ptr) {
0167   if (ptr) {
0168     _inputStrings[type] = ptr;
0169   } else {
0170     _inputStrings.remove(type);
0171   }
0172 }
0173 
0174 PrimitiveList DataObject::inputPrimitives() const {
0175   PrimitiveList primitive_list;
0176 
0177   int n = _inputMatrices.count();
0178   for (int i = 0; i< n; i++) {
0179       primitive_list.append(kst_cast<Primitive>(_inputMatrices.values().at(i)));
0180   }
0181 
0182   n = _inputStrings.count();
0183   for (int i = 0; i< n; i++) {
0184       primitive_list.append(kst_cast<Primitive>(_inputStrings.values().at(i)));
0185   }
0186 
0187   n = _inputScalars.count();
0188   for (int i = 0; i< n; i++) {
0189       primitive_list.append(kst_cast<Primitive>(_inputScalars.values().at(i)));
0190   }
0191 
0192   n = _inputVectors.count();
0193   for (int i = 0; i< n; i++) {
0194       primitive_list.append(kst_cast<Primitive>(_inputVectors.values().at(i)));
0195   }
0196 
0197   return primitive_list;
0198 }
0199 
0200 
0201 PrimitiveList DataObject::outputPrimitives(bool include_decendants)  const {
0202   PrimitiveList primitive_list;
0203 
0204   int n = _outputMatrices.count();
0205   for (int i = 0; i< n; i++) {
0206       primitive_list.append(kst_cast<Primitive>(_outputMatrices.values().at(i)));
0207       if (include_decendants) {
0208           primitive_list.append(_outputMatrices.values().at(i)->outputPrimitives());
0209       }
0210   }
0211 
0212   n = _outputStrings.count();
0213   for (int i = 0; i< n; i++) {
0214       primitive_list.append(kst_cast<Primitive>(_outputStrings.values().at(i)));
0215       if (include_decendants) {
0216           primitive_list.append(_outputStrings.values().at(i)->outputPrimitives());
0217       }
0218   }
0219 
0220   n = _outputScalars.count();
0221   for (int i = 0; i< n; i++) {
0222       primitive_list.append(kst_cast<Primitive>(_outputScalars.values().at(i)));
0223       if (include_decendants) {
0224           primitive_list.append(_outputScalars.values().at(i)->outputPrimitives());
0225       }
0226   }
0227 
0228   n = _outputVectors.count();
0229   for (int i = 0; i< n; i++) {
0230       primitive_list.append(kst_cast<Primitive>(_outputVectors.values().at(i)));
0231       if (include_decendants) {
0232           primitive_list.append(_outputVectors.values().at(i)->outputPrimitives());
0233       }
0234   }
0235 
0236   return primitive_list;
0237 }
0238 
0239 
0240 // set flags on all output primitives
0241 // used for sorting dataobjects by Document::sortedDataObjectList()
0242 void DataObject::setOutputFlags(bool flag) {
0243   PrimitiveList output_primitives = outputPrimitives();
0244   int n = output_primitives.count();
0245   for (int i=0; i<n; i++) {
0246     output_primitives[i]->setFlag(flag);
0247   }
0248 }
0249 
0250 
0251 bool DataObject::inputFlagsSet() const {
0252   PrimitiveList input_primitives = inputPrimitives();
0253   int n = input_primitives.count();
0254   bool all_set = true;
0255   for (int i=0; i<n; i++) {
0256     all_set &= input_primitives[i]->flagSet();
0257   }
0258 
0259   return all_set;
0260 }
0261 
0262 // Scans for plugins and stores the information for them
0263 void DataObject::scanPlugins() {
0264   Debug::self()->log(tr("Scanning for data-object plugins."));
0265 
0266   _pluginList.clear(); //FIXME?
0267 
0268   DataObjectPluginList tmpList;
0269 
0270   Debug::self()->log(tr("Scanning for data-object plugins."));
0271 
0272   foreach (QObject *plugin, QPluginLoader::staticInstances()) {
0273     //try a cast
0274     if (DataObjectPluginInterface *basicPlugin = qobject_cast<DataObjectPluginInterface*>(plugin)) {
0275       tmpList.append(basicPlugin);
0276     }
0277   }
0278 
0279   QStringList pluginPaths = pluginSearchPaths();
0280   foreach (const QString &pluginPath, pluginPaths) {
0281     QDir d(pluginPath);
0282     foreach (const QString &fileName, d.entryList(QDir::Files)) {
0283         QPluginLoader loader(d.absoluteFilePath(fileName));
0284         QObject *plugin = loader.instance();
0285         if (plugin) {
0286           if (DataObjectPluginInterface *dataObjectPlugin = qobject_cast<DataObjectPluginInterface*>(plugin)) {
0287             tmpList.append(dataObjectPlugin);
0288             Debug::self()->log(QString("Plugin loaded: %1").arg(fileName));
0289           }
0290         } else {
0291           Debug::self()->log(QString("Plugin failed to load: %1").arg(fileName));
0292         }
0293     }
0294   }
0295 
0296   // This cleans up plugins that have been uninstalled and adds in new ones.
0297   // Since it is a shared pointer it can't dangle anywhere.
0298   _pluginList.clear();
0299   _pluginList = tmpList;
0300 }
0301 
0302 
0303 void DataObject::initPlugins() {
0304   if (_pluginList.isEmpty()) {
0305       scanPlugins();
0306   }
0307 }
0308 
0309 
0310 QStringList DataObject::pluginList() {
0311   // Ensure state.  When using kstapp MainWindow calls init.
0312   init();
0313 
0314   QStringList plugins;
0315 
0316   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0317     plugins += (*it)->pluginName();
0318   }
0319 
0320   return plugins;
0321 }
0322 
0323 
0324 QStringList DataObject::dataObjectPluginList() {
0325   // Ensure state.  When using kstapp MainWindow calls init.
0326   init();
0327 
0328   QStringList plugins;
0329 
0330   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0331     if ((*it)->pluginType() == DataObjectPluginInterface::Generic) {
0332       plugins += (*it)->pluginName();
0333     }
0334   }
0335 
0336   plugins.sort();
0337   return plugins;
0338 }
0339 
0340 
0341 QStringList DataObject::filterPluginList() {
0342   // Ensure state.  When using kstapp MainWindow calls init.
0343   init();
0344 
0345   QStringList plugins;
0346 
0347   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0348     if ((*it)->pluginType() == DataObjectPluginInterface::Filter) {
0349       plugins += (*it)->pluginName();
0350     }
0351   }
0352 
0353   plugins.sort();
0354   return plugins;
0355 }
0356 
0357 
0358 QStringList DataObject::fitsPluginList() {
0359   // Ensure state.  When using kstapp MainWindow calls init.
0360   init();
0361 
0362   QStringList plugins;
0363 
0364   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0365     if ((*it)->pluginType() == DataObjectPluginInterface::Fit) {
0366       plugins += (*it)->pluginName();
0367     }
0368   }
0369 
0370   plugins.sort();
0371   return plugins;
0372 }
0373 
0374 
0375 DataObjectConfigWidget* DataObject::pluginWidget(const QString& name) {
0376   // Ensure state.  When using kstapp MainWindow calls init.
0377   init();
0378 
0379   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0380     if ((*it)->pluginName() == name) {
0381       if ((*it)->hasConfigWidget()) {
0382 
0383         return (*it)->configWidget(&settingsObject());
0384       }
0385       break;
0386     }
0387   }
0388   return 0L;
0389 }
0390 
0391 
0392 QString DataObject::pluginDescription(const QString& name) {
0393   // Ensure state.  When using kstapp MainWindow calls init.
0394   init();
0395 
0396   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0397     if ((*it)->pluginName() == name) {
0398       return (*it)->pluginDescription();
0399     }
0400   }
0401   return QString();
0402 }
0403 
0404 
0405 int DataObject::pluginType(const QString& name) {
0406   // Ensure state.  When using kstapp MainWindow calls init.
0407   init();
0408 
0409   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0410     if ((*it)->pluginName() == name) {
0411       return (*it)->pluginType();
0412     }
0413   }
0414   return -1;
0415 }
0416 
0417 
0418 DataObjectPtr DataObject::createPlugin(const QString& name, ObjectStore *store, DataObjectConfigWidget *configWidget, bool setupInputsOutputs) {
0419   // Ensure state.  When using kstapp MainWindow calls init.
0420   init();
0421 
0422   for (DataObjectPluginList::ConstIterator it = _pluginList.constBegin(); it != _pluginList.constEnd(); ++it) {
0423     if ((*it)->pluginName() == name) {
0424       if (DataObjectPtr object = (*it)->create(store, configWidget, setupInputsOutputs)) {
0425         return object;
0426       }
0427     }
0428   }
0429 
0430 #if 0
0431   KService::List sl = KServiceTypeTrader::self()->query("Kst Data Object");
0432   for (KService::List::ConstIterator it = sl.constBegin(); it != sl.constEnd(); ++it) {
0433     if ((*it)->name() != name) {
0434       continue;
0435     } else if (DataObjectPtr object = createPlugin(*it)) {
0436       return object;
0437     }
0438   }
0439 #endif
0440   return 0L;
0441 }
0442 
0443 
0444 #if 0
0445 double *DataObject::vectorRealloced(VectorPtr v, double *memptr, int newSize) const {
0446   if (!v) {
0447     return 0L;
0448   }
0449 
0450   // One would think this needs special locking, but it results in deadlock
0451   // in complicated object hierarchies such as filtered vectors.  Therefore if
0452   // you call vectorRealloced() and v is not locked by you already, you'd
0453   // better lock it!
0454   return v->realloced(memptr, newSize);
0455 }
0456 #endif
0457 
0458 void DataObject::load(const QXmlStreamReader &e) {
0459   qDebug() << QString("FIXME! Loading of %1 is not implemented yet.").arg(typeString()) << endl;
0460   Q_UNUSED(e)
0461 }
0462 
0463 
0464 void DataObject::save(QXmlStreamWriter& ts) {
0465   qDebug() << QString("FIXME! Saving of %1 is not implemented yet.").arg(typeString()) << endl;
0466   Q_UNUSED(ts)
0467 }
0468 
0469 int DataObject::getUsage() const {
0470   int rc = 0;
0471 
0472   for (VectorMap::ConstIterator i = _outputVectors.constBegin(); i != _outputVectors.constEnd(); ++i) {
0473     if (i.value().data()) {
0474       rc += i.value()->getUsage() - 1;
0475     }
0476   }
0477 
0478   for (ScalarMap::ConstIterator i = _outputScalars.constBegin(); i != _outputScalars.constEnd(); ++i) {
0479     if (i.value().data()) {
0480       rc += i.value()->getUsage() - 1;
0481     }
0482   }
0483 
0484   for (StringMap::ConstIterator i = _outputStrings.constBegin(); i != _outputStrings.constEnd(); ++i) {
0485     if (i.value().data()) {
0486       rc += i.value()->getUsage() - 1;
0487     }
0488   }
0489 
0490   for (MatrixMap::ConstIterator i = _outputMatrices.constBegin(); i != _outputMatrices.constEnd(); ++i) {
0491     if (i.value().data()) {
0492       rc += i.value()->getUsage() - 1;
0493     }
0494   }
0495 
0496   return Object::getUsage() + rc;
0497 }
0498 
0499 
0500 void DataObject::showDialog(bool isNew) {
0501   if (isNew) {
0502     QTimer::singleShot(0, this, SLOT(showNewDialog()));
0503   } else {
0504     QTimer::singleShot(0, this, SLOT(showEditDialog()));
0505   }
0506 }
0507 
0508 
0509 void DataObject::readLock() const {
0510   #ifdef LOCKTRACE
0511   qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::readLock() by tid=" << (int)QThread::currentThread() << ": read locking myself" << endl;
0512   #endif
0513 
0514   Object::readLock();
0515 }
0516 
0517 
0518 void DataObject::writeLock() const {
0519   #ifdef LOCKTRACE
0520   qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::writeLock() by tid=" << (int)QThread::currentThread() << ": write locking myself" << endl;
0521   #endif
0522 
0523   Object::writeLock();
0524 }
0525 
0526 
0527 void DataObject::unlock() const {
0528   #ifdef LOCKTRACE
0529   qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlock() by tid=" << (int)QThread::currentThread() << ": unlocking myself" << endl;
0530   #endif
0531 
0532   Object::unlock();
0533 }
0534 
0535 
0536 void DataObject::writeLockInputsAndOutputs() const {
0537   Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED);
0538 
0539   #ifdef LOCKTRACE
0540   qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::writeLockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << endl;
0541   #endif
0542 
0543   QList<PrimitivePtr> inputs;
0544   QList<PrimitivePtr> outputs;
0545 
0546   QList<StringPtr> sl = _inputStrings.values();
0547   for (QList<StringPtr>::Iterator i = sl.begin(); i != sl.end(); ++i) {
0548     inputs += (*i).data();
0549   }
0550   sl = _outputStrings.values();
0551   for (QList<StringPtr>::Iterator i = sl.begin(); i != sl.end(); ++i) {
0552     outputs += (*i).data();
0553   }
0554 
0555   QList<ScalarPtr> sc = _inputScalars.values();
0556   for (QList<ScalarPtr>::Iterator i = sc.begin(); i != sc.end(); ++i) {
0557     inputs += (*i).data();
0558   }
0559   sc = _outputScalars.values();
0560   for (QList<ScalarPtr>::Iterator i = sc.begin(); i != sc.end(); ++i) {
0561     outputs += (*i).data();
0562   }
0563 
0564   QList<VectorPtr> vl = _inputVectors.values();
0565   for (QList<VectorPtr>::Iterator i = vl.begin(); i != vl.end(); ++i) {
0566     inputs += (*i).data();
0567   }
0568   vl = _outputVectors.values();
0569   for (QList<VectorPtr>::Iterator i = vl.begin(); i != vl.end(); ++i) {
0570     outputs += (*i).data();
0571   }
0572 
0573   QList<MatrixPtr> ml = _inputMatrices.values();
0574   for (QList<MatrixPtr>::Iterator i = ml.begin(); i != ml.end(); ++i) {
0575     inputs += (*i).data();
0576   }
0577   ml = _outputMatrices.values();
0578   for (QList<MatrixPtr>::Iterator i = ml.begin(); i != ml.end(); ++i) {
0579     outputs += (*i).data();
0580   }
0581 
0582   qSort(inputs);
0583   qSort(outputs);
0584 
0585   QList<PrimitivePtr>::ConstIterator inputIt = inputs.constBegin();
0586   QList<PrimitivePtr>::ConstIterator outputIt = outputs.constBegin();
0587 
0588   while (inputIt != inputs.constEnd() || outputIt != outputs.constEnd()) {
0589     if (inputIt != inputs.constEnd() && (outputIt == outputs.constEnd() || (void*)(*inputIt) < (void*)(*outputIt))) {
0590       // do input
0591       if (!(*inputIt)) {
0592         qWarning() << "Input for data object " << this->Name() << " is invalid." << endl;
0593       }
0594 #ifdef LOCKTRACE
0595       qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::writeLockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": write locking input \"" << (*inputIt)->Name() << "\" (" << (void*)((KstRWLock*)*inputIt) << ")" << endl;
0596 #endif
0597       (*inputIt)->writeLock();
0598       ++inputIt;
0599     } else {
0600       // do output
0601       if (!(*outputIt)) {
0602         qWarning() << "Output for data object " << this->Name() << " is invalid." << endl;
0603       }
0604 #ifdef LOCKTRACE
0605       qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::writeLockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": write locking output \"" << (*outputIt)->Name() << "\" (" << (void*)((KstRWLock*)*outputIt) << ")" << endl;
0606 #endif
0607       if ((*outputIt)->provider() != this) {
0608         Debug::self()->log(tr("(%1) DataObject::writeLockInputsAndOutputs() by tid=%2: write locking output %3 (not provider) -- this is probably an error. Please email kst@kde.org with details.").arg(this->type()).arg(reinterpret_cast<qint64>(QThread::currentThread())).arg((*outputIt)->Name()), Debug::Error);
0609       }
0610 
0611       (*outputIt)->writeLock();
0612       ++outputIt;
0613     }
0614   }
0615 }
0616 
0617 
0618 void DataObject::unlockInputsAndOutputs() const {
0619   #ifdef LOCKTRACE
0620   qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << endl;
0621   #endif
0622 
0623   for (MatrixMap::ConstIterator i = _outputMatrices.constBegin(); i != _outputMatrices.constEnd(); ++i) {
0624     if (!(*i)) {
0625       qWarning() << "Output matrix for data object " << this->Name() << " is invalid." << endl;
0626     }
0627     #ifdef LOCKTRACE
0628     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output matrix \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0629     #endif
0630     (*i)->unlock();
0631   }
0632 
0633   for (MatrixMap::ConstIterator i = _inputMatrices.constBegin(); i != _inputMatrices.constEnd(); ++i) {
0634     if (!(*i)) {
0635       qWarning() << "Input matrix for data object " << this->Name() << " is invalid." << endl;
0636     }
0637     #ifdef LOCKTRACE
0638     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input matrix \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0639     #endif
0640     (*i)->unlock();
0641   }
0642 
0643   for (VectorMap::ConstIterator i = _outputVectors.constBegin(); i != _outputVectors.constEnd(); ++i) {
0644     if (!(*i)) {
0645       qWarning() << "Output vector for data object " << this->Name() << " is invalid." << endl;
0646     }
0647     #ifdef LOCKTRACE
0648     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output vector \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0649     #endif
0650     (*i)->unlock();
0651   }
0652 
0653   for (VectorMap::ConstIterator i = _inputVectors.constBegin(); i != _inputVectors.constEnd(); ++i) {
0654     if (!(*i)) {
0655       qWarning() << "Input vector for data object " << this->Name() << " is invalid." << endl;
0656     }
0657     #ifdef LOCKTRACE
0658     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input vector \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0659     #endif
0660     (*i)->unlock();
0661   }
0662 
0663   for (ScalarMap::ConstIterator i = _outputScalars.constBegin(); i != _outputScalars.constEnd(); ++i) {
0664     if (!(*i)) {
0665       qWarning() << "Output scalar for data object " << this->Name() << " is invalid." << endl;
0666     }
0667     #ifdef LOCKTRACE
0668     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output scalar \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0669     #endif
0670     (*i)->unlock();
0671   }
0672 
0673   for (ScalarMap::ConstIterator i = _inputScalars.constBegin(); i != _inputScalars.constEnd(); ++i) {
0674     if (!(*i)) {
0675       qWarning() << "Input scalar for data object " << this->Name() << " is invalid." << endl;
0676     }
0677     #ifdef LOCKTRACE
0678     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input scalar \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0679     #endif
0680     (*i)->unlock();
0681   }
0682 
0683   for (StringMap::ConstIterator i = _outputStrings.constBegin(); i != _outputStrings.constEnd(); ++i) {
0684     if (!(*i)) {
0685       qWarning() << "Output string for data object " << this->Name() << " is invalid." << endl;
0686     }
0687    #ifdef LOCKTRACE
0688     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output string \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0689     #endif
0690     (*i)->unlock();
0691   }
0692 
0693   for (StringMap::ConstIterator i = _inputStrings.constBegin(); i != _inputStrings.constEnd(); ++i) {
0694     if (!(*i)) {
0695       qWarning() << "Input string for data object " << this->Name() << " is invalid." << endl;
0696     }
0697     #ifdef LOCKTRACE
0698     qDebug() << (void*)this << " (" << this->type() << ": " << this->Name() << ") DataObject::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input string \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl;
0699     #endif
0700     (*i)->unlock();
0701   }
0702 }
0703 
0704 
0705 bool DataObject::isValid() {
0706   return true;
0707 }
0708 
0709 
0710 const CurveHintList* DataObject::curveHints() const {
0711   return _curveHints;
0712 }
0713 
0714 
0715 void DataObject::deleteDependents() {
0716   DataObjectList dataObjects = _store->getObjects<DataObject>();
0717   foreach (const DataObjectPtr &object, dataObjects) {
0718     bool usesObject = object->uses(this);
0719     if (!usesObject) {
0720       for (VectorMap::Iterator j = _outputVectors.begin(); !usesObject && j != _outputVectors.end(); ++j) {
0721         usesObject = object->uses(j.value().data());
0722       }
0723       for (ScalarMap::Iterator j = _outputScalars.begin(); !usesObject && j != _outputScalars.end(); ++j) {
0724         usesObject = object->uses(j.value().data());
0725       }
0726       for (StringMap::Iterator j = _outputStrings.begin(); !usesObject && j != _outputStrings.end(); ++j) {
0727         usesObject = object->uses(j.value().data());
0728       }
0729       for (MatrixMap::Iterator j = _outputMatrices.begin(); !usesObject && j != _outputMatrices.end(); ++j) {
0730         usesObject = object->uses(j.value().data());
0731       }
0732     }
0733     if (usesObject) {
0734       _store->removeObject(object);
0735     }
0736   }
0737 
0738   RelationList relations = _store->getObjects<Relation>();
0739   foreach (const RelationPtr &relation, relations) {
0740     bool usesRelation = relation->uses(this);
0741     if (!usesRelation) {
0742       for (VectorMap::Iterator j = _outputVectors.begin(); !usesRelation && j != _outputVectors.end(); ++j) {
0743         usesRelation = relation->uses(j.value().data());
0744       }
0745       for (ScalarMap::Iterator j = _outputScalars.begin(); !usesRelation && j != _outputScalars.end(); ++j) {
0746         usesRelation = relation->uses(j.value().data());
0747       }
0748       for (StringMap::Iterator j = _outputStrings.begin(); !usesRelation && j != _outputStrings.end(); ++j) {
0749         usesRelation = relation->uses(j.value().data());
0750       }
0751       for (MatrixMap::Iterator j = _outputMatrices.begin(); !usesRelation && j != _outputMatrices.end(); ++j) {
0752         usesRelation = relation->uses(j.value().data());
0753       }
0754     }
0755     if (usesRelation) {
0756       _store->removeObject(relation);
0757     }
0758   }
0759 
0760   foreach (const VectorPtr &vector, _outputVectors) {
0761     _store->removeObject(vector);
0762   }
0763   foreach (const MatrixPtr &matrix, _outputMatrices) {
0764     _store->removeObject(matrix);
0765   }
0766   foreach (const ScalarPtr &scalar, _outputScalars) {
0767     _store->removeObject(scalar);
0768   }
0769   foreach (const StringPtr &string, _outputStrings) {
0770     _store->removeObject(string);
0771   }
0772 }
0773 
0774 
0775 bool DataObject::uses(ObjectPtr p) const {
0776   PrimitiveList this_input_primitives;
0777   PrimitiveList p_output_primitives;
0778 
0779   this_input_primitives = inputPrimitives();
0780 
0781   PrimitivePtr p_prim = kst_cast<Primitive>(p);
0782   DataObjectPtr p_dobj = kst_cast<DataObject>(p);
0783 
0784   if (p_prim) {
0785     p_output_primitives = p_prim->outputPrimitives();
0786     p_output_primitives << p_prim; // include the object itself.
0787   } else if (p_dobj) {
0788     p_output_primitives = p_dobj->outputPrimitives();
0789   }  else {
0790     p_output_primitives.clear();
0791   }
0792 
0793   // now check if any of this's input primitives are one of p's output primitives...
0794   int n_in = this_input_primitives.count();
0795   for (int i_in = 0; i_in<n_in; i_in++) {
0796     PrimitivePtr p_in = this_input_primitives.at(i_in);
0797     if (p_output_primitives.contains(p_in)) {
0798       return true;
0799     }
0800   }
0801   return false;
0802 }
0803 
0804 qint64 DataObject::minInputSerial() const{
0805   qint64 minSerial = LLONG_MAX;
0806 
0807   foreach (const VectorPtr &P, _inputVectors) {
0808     minSerial = qMin(minSerial, P->serial());
0809   }
0810   foreach (const ScalarPtr &P, _inputScalars) {
0811     minSerial = qMin(minSerial, P->serial());
0812   }
0813   foreach (const MatrixPtr &P, _inputMatrices) {
0814     minSerial = qMin(minSerial, P->serial());
0815   }
0816   foreach (const StringPtr &P, _inputStrings) {
0817     minSerial = qMin(minSerial, P->serial());
0818   }
0819   return minSerial;
0820 }
0821 
0822 qint64 DataObject::maxInputSerialOfLastChange() const {
0823   qint64 maxSerial = NoInputs;
0824 
0825   foreach (const VectorPtr &P, _inputVectors) {
0826     maxSerial = qMax(maxSerial, P->serialOfLastChange());
0827   }
0828   foreach (const ScalarPtr &P, _inputScalars) {
0829     maxSerial = qMax(maxSerial, P->serialOfLastChange());
0830   }
0831   foreach (const MatrixPtr &P, _inputMatrices) {
0832     maxSerial = qMax(maxSerial, P->serialOfLastChange());
0833   }
0834   foreach (const StringPtr &P, _inputStrings) {
0835     maxSerial = qMax(maxSerial, P->serialOfLastChange());
0836   }
0837   return maxSerial;
0838 }
0839 
0840 
0841 /////////////////////////////////////////////////////////////////////////////
0842 DataObjectConfigWidget::DataObjectConfigWidget(QSettings *cfg)
0843 : QWidget(0L), _cfg(cfg) {
0844 }
0845 
0846 
0847 DataObjectConfigWidget::~DataObjectConfigWidget() {
0848 }
0849 
0850 
0851 void DataObjectConfigWidget::save() {
0852 }
0853 
0854 
0855 void DataObjectConfigWidget::load() {
0856 }
0857 
0858 
0859 void DataObjectConfigWidget::setObjectStore(ObjectStore* store) {
0860   Q_UNUSED(store);
0861 }
0862 
0863 
0864 void DataObjectConfigWidget::setupFromObject(Object* dataObject) {
0865   Q_UNUSED(dataObject);
0866 }
0867 
0868 
0869 void DataObjectConfigWidget::setVectorX(VectorPtr vector) {
0870   Q_UNUSED(vector);
0871 }
0872 
0873 
0874 void DataObjectConfigWidget::setVectorY(VectorPtr vector) {
0875   Q_UNUSED(vector);
0876 }
0877 
0878 
0879 void DataObjectConfigWidget::setupSlots(QWidget* dialog) {
0880   Q_UNUSED(dialog);
0881 }
0882 
0883 
0884 void DataObjectConfigWidget::setVectorsLocked(bool locked) {
0885   Q_UNUSED(locked);
0886 }
0887 
0888 
0889 bool DataObjectConfigWidget::configurePropertiesFromXml(ObjectStore *store, QXmlStreamAttributes& attrs) {
0890   Q_UNUSED(store);
0891   Q_UNUSED(attrs);
0892   return true;
0893 }
0894 
0895 QByteArray DataObject::scriptInterface(QList<QByteArray> &c) {
0896   Q_ASSERT(c.size());
0897   if(c[0]=="outputVectorHandle") {
0898     if (c.size()==2) {
0899       QString c1 = QString(c[1]).trimmed();
0900       if (_outputVectors.contains(c1)) {
0901         return _outputVectors[c1]->Name().toAscii();
0902       } else {
0903         return QByteArray("vector not found: ").append(c[1]);
0904       }
0905     } else {
0906       return "outputVectorHandle takes one arg";
0907     }
0908   } else if(c[0]=="outputScalarHandle") {
0909     if (c.size()==2) {
0910       QString c1 = QString(c[1]).trimmed();
0911       if (_outputScalars.contains(c1)) {
0912         return _outputScalars[c1]->Name().toAscii();
0913       } else {
0914         return QByteArray("scalar not found: ").append(c[1]);
0915       }
0916     } else {
0917       return "outputScalarHandle takes one arg";
0918     }
0919   } else if(c[0]=="outputMatrixHandle") {
0920     if (c.size()==2) {
0921       QString c1 = QString(c[1]).trimmed();
0922       if (_outputMatrices.contains(c1)) {
0923         return _outputMatrices[c1]->Name().toAscii();
0924       } else {
0925         return QByteArray("Matrix not found: ").append(c[1]);
0926       }
0927     } else {
0928       return "outputMatrixHandle takes one arg";
0929     }
0930   } else if(c[0]=="outputStringHandle") {
0931     if (c.size()==2) {
0932       QString c1 = QString(c[1]).trimmed();
0933       if (_outputStrings.contains(c1)) {
0934         return _outputStrings[c1]->Name().toAscii();
0935       } else {
0936         return QByteArray("String not found: ").append(c[1]);
0937       }
0938     } else {
0939       return "outputStringHandle takes one arg";
0940     }
0941   }
0942 
0943   return "No such command...";
0944 }
0945 
0946 // vim: ts=2 sw=2 et