1 /***************************************************************************
2  *                                                                         *
3  *   copyright : (C) 2007 The University of Toronto                        *
4  *                   netterfield@astro.utoronto.ca                         *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  ***************************************************************************/
12 
13 #include "basicplugin.h"
14 
15 #include <stdlib.h>
16 
17 #include <QXmlStreamWriter>
18 
19 #ifndef Q_OS_WIN32
20 #include <unistd.h>
21 #endif
22 
23 
24 
25 #include "debug.h"
26 #include "dialoglauncher.h"
27 #include "datacollection.h"
28 #include "objectstore.h"
29 #include "dataobjectplugin.h"
30 #include "dataobjectscriptinterface.h"
31 
32 namespace Kst {
33 
34 const QString BasicPlugin::staticTypeString = "Plugin";
35 const QString BasicPlugin::staticTypeTag = "plugin";
36 
BasicPlugin(ObjectStore * store)37 BasicPlugin::BasicPlugin(ObjectStore *store)
38 : DataObject(store) {
39   _typeString = "Plugin";
40   _type = "Plugin";
41 
42   _initializeShortName();
43 }
44 
45 
~BasicPlugin()46 BasicPlugin::~BasicPlugin() {
47 }
48 
_initializeShortName()49 void BasicPlugin::_initializeShortName() {
50   _shortName = 'U'+QString::number(_pluginnum);
51   if (_pluginnum>max_pluginnum)
52     max_pluginnum = _pluginnum;
53   _pluginnum++;
54 
55 }
56 
57 
createScriptInterface()58 ScriptInterface* BasicPlugin::createScriptInterface() {
59   return new PluginSI(this);
60 }
61 
62 
setPluginName(const QString & pluginName)63 void BasicPlugin::setPluginName(const QString &pluginName) {
64   _pluginName = pluginName;
65 }
66 
67 
makeDuplicate() const68 DataObjectPtr BasicPlugin::makeDuplicate() const {
69 #if 0
70   BasicPluginPtr plugin = kst_cast<BasicPlugin>(DataObject::createPlugin(propertyString()));
71 
72   // use same inputs
73   for (VectorMap::ConstIterator iter = _inputVectors.begin(); iter != _inputVectors.end(); ++iter) {
74     plugin->inputVectors().insert(iter.key(), iter.value());
75   }
76   for (ScalarMap::ConstIterator iter = _inputScalars.begin(); iter != _inputScalars.end(); ++iter) {
77     plugin->inputScalars().insert(iter.key(), iter.value());
78   }
79   for (StringMap::ConstIterator iter = _inputStrings.begin(); iter != _inputStrings.end(); ++iter) {
80     plugin->inputStrings().insert(iter.key(), iter.value());
81   }
82 
83   // create new outputs
84   for (VectorMap::ConstIterator iter = outputVectors().begin(); iter != outputVectors().end(); ++iter) {
85     KstWriteLocker blockVectorUpdates(&vectorList.lock());
86     VectorPtr v = new Vector(ObjectTag(iter.value()->tag().tag() + "'", iter.value()->tag().context()), 0, plugin.data()); // FIXME: unique tag generation
87     plugin->outputVectors().insert(iter.key(), v);
88   }
89   for (ScalarMap::ConstIterator iter = outputScalars().begin(); iter != outputScalars().end(); ++iter) {
90     ScalarPtr s = new Scalar(ObjectTag(iter.value()->tag().tag() + "'", iter.value()->tag().context()), plugin.data()); // FIXME: unique tag generation
91     plugin->outputScalars().insert(iter.key(), s);
92   }
93   for (StringMap::ConstIterator iter = outputStrings().begin(); iter != outputStrings().end(); ++iter) {
94     StringPtr s = new String(ObjectTag(iter.value()->tag().tag() + "'", iter.value()->tag().context()), plugin.data()); // FIXME: unique tag generation
95     plugin->outputStrings().insert(iter.key(), s);
96   }
97 
98   // set the same plugin
99   plugin->setTagName(ObjectTag(tag().tag() + "'", tag().context())); // FIXME: unique tag generation method
100   map.insert(this, DataObjectPtr(plugin));
101   return DataObjectPtr(plugin);
102 #endif
103   // FIXME: implement this
104   return 0L;
105 }
106 
showNewDialog()107 void BasicPlugin::showNewDialog() {
108   DialogLauncher::self()->showBasicPluginDialog(_pluginName);
109 }
110 
111 
showEditDialog()112 void BasicPlugin::showEditDialog() {
113   DialogLauncher::self()->showBasicPluginDialog(_pluginName, this);
114 }
115 
116 
inputVector(const QString & vector) const117 VectorPtr BasicPlugin::inputVector(const QString& vector) const {
118   VectorMap::ConstIterator i = _inputVectors.constFind(vector);
119   if (i != _inputVectors.constEnd())
120     return *i;
121   else
122     return 0;
123 }
124 
125 
inputScalar(const QString & scalar) const126 ScalarPtr BasicPlugin::inputScalar(const QString& scalar) const {
127   ScalarMap::ConstIterator i = _inputScalars.constFind(scalar);
128   if (i != _inputScalars.constEnd())
129     return *i;
130   else
131     return 0;
132 }
133 
134 
inputString(const QString & string) const135 StringPtr BasicPlugin::inputString(const QString& string) const {
136   StringMap::ConstIterator i = _inputStrings.constFind(string);
137   if (i != _inputStrings.constEnd())
138     return *i;
139   else
140     return 0;
141 }
142 
143 
setOutputVector(const QString & type,const QString & name)144 void BasicPlugin::setOutputVector(const QString &type, const QString &name) {
145   QString txt = !name.isEmpty() ? name : type;
146   Q_ASSERT(store());
147   VectorPtr v = store()->createObject<Vector>();
148   v->setProvider(this);
149   v->setSlaveName(txt);
150   _outputVectors.insert(type, v);
151 }
152 
153 
setOutputScalar(const QString & type,const QString & name)154 void BasicPlugin::setOutputScalar(const QString &type, const QString &name) {
155   QString txt = !name.isEmpty() ? name : type;
156   Q_ASSERT(store());
157   ScalarPtr s = store()->createObject<Scalar>();
158   s->setProvider(this);
159   s->setSlaveName(txt);
160   _outputScalars.insert(type, s);
161 }
162 
163 
setOutputString(const QString & type,const QString & name)164 void BasicPlugin::setOutputString(const QString &type, const QString &name) {
165   QString txt = !name.isEmpty() ? name : type;
166   Q_ASSERT(store());
167   StringPtr s = store()->createObject<String>();
168   s->setProvider(this);
169   s->setSlaveName(txt);
170   s->setOrphan(false);
171   _outputStrings.insert(type, s);
172 }
173 
174 
internalUpdate()175 void BasicPlugin::internalUpdate() {
176 
177   //Make sure we have all the necessary inputs
178   if (!inputsExist())
179     return;
180 
181   writeLockInputsAndOutputs();
182 
183   //Call the plugins algorithm to operate on the inputs
184   //and produce the outputs
185   if ( !algorithm() ) {
186     Debug::self()->log(tr("There is an error in the %1 algorithm.").arg(propertyString()), Debug::Error);
187     unlockInputsAndOutputs();
188     return;
189   }
190 
191   // Register that the outputs have been recalculated.
192   updateOutput();
193 
194   createScalars();
195 
196   unlockInputsAndOutputs();
197 
198   return;
199 }
200 
201 
202 // If a plugin provides a Parameters Vector, then scalars will be created, as well as a label.
createScalars()203 void BasicPlugin::createScalars() {
204   // Assumes that this is called with a write lock in place on this object
205   Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED);
206 
207   if (hasParameterVector()) {
208     VectorPtr vectorParam = _outputVectors["Parameters Vector"];
209     if (vectorParam) {
210       QString paramName;
211       int i = 0;
212       int length = vectorParam->length();
213 
214       Q_ASSERT(store());
215       for (paramName = parameterName(i);
216           !paramName.isEmpty() && i < length;
217            paramName = parameterName(++i)) {
218         double scalarValue = vectorParam->value(i);
219         if (!_outputScalars.contains(paramName)) {
220           ScalarPtr s = store()->createObject<Scalar>();
221           s->setProvider(this);
222           s->setSlaveName(paramName);
223           s->setValue(scalarValue);
224           s->writeLock();
225           _outputScalars.insert(paramName, s);
226         } else {
227           _outputScalars[paramName]->setValue(scalarValue);
228         }
229       }
230     }
231   }
232 }
233 
234 
parameterName(int) const235 QString BasicPlugin::parameterName(int /*index*/) const {
236     return QString();
237 }
238 
239 
label(int precision) const240 QString BasicPlugin::label(int precision) const {
241   Q_UNUSED(precision)
242   QString label;
243   QString paramName;
244 
245   VectorPtr yVector = outputVectors().value(outputVectorList().first());
246 
247   label = yVector->labelInfo().name;
248 
249   if (hasParameterVector()) {
250     VectorPtr vectorParam = _outputVectors["Parameters Vector"];
251     int length = vectorParam->length();
252     int i=0;
253     for (paramName = parameterName(i);
254          !paramName.isEmpty() && i < length;
255          paramName = parameterName(++i)) {
256         if (_outputScalars.contains(paramName)) {
257           label += QString("\n%1: [%2]").arg(paramName).arg(_outputScalars[paramName]->Name());
258         }
259     }
260   }
261 
262   return label;
263 }
264 
265 
266 template<class T, class V>
writeVectors(T & vectors,const QString & element,QXmlStreamWriter & stream,QString (V::* name)()const)267 static void writeVectors(T& vectors, const QString& element, QXmlStreamWriter& stream, QString (V::* name)() const) {
268   for (QStringList::iterator it = vectors.ordered.begin(); it != vectors.ordered.end(); ++it) {
269     typename T::iterator i = vectors.find(*it);
270     stream.writeStartElement(element);
271     stream.writeAttribute("type", i.key());
272     stream.writeAttribute("tag", (i.value()->*name)());
273     stream.writeEndElement();
274   }
275 }
276 
277 
save(QXmlStreamWriter & stream)278 void BasicPlugin::save(QXmlStreamWriter &stream) {
279   stream.writeStartElement(staticTypeTag);
280   stream.writeAttribute("type", _pluginName);
281   saveNameInfo(stream, VECTORNUM|PLUGINNUM|SCALARNUM);
282   saveProperties(stream);
283   writeVectors(_inputVectors, "inputvector", stream, &NamedObject::Name);
284   writeVectors(_inputScalars, "inputscalar", stream, &NamedObject::Name);
285   writeVectors(_inputStrings, "inputstring", stream, &NamedObject::Name);
286   writeVectors(_outputVectors, "outputvector", stream, &Primitive::slaveName);
287   writeVectors(_outputScalars, "outputscalar", stream, &Primitive::slaveName);
288   writeVectors(_outputStrings, "outputstring", stream, &Primitive::slaveName);
289 
290   stream.writeEndElement();
291 }
292 
293 
saveProperties(QXmlStreamWriter & s)294 void BasicPlugin::saveProperties(QXmlStreamWriter &s) {
295   Q_UNUSED(s);
296 }
297 
298 
299 //TODO Could use some templates perhaps...
inputsExist() const300 bool BasicPlugin::inputsExist() const {
301   //First, check the inputVectors...
302   QStringList iv = inputVectorList();
303   QStringList::ConstIterator ivI = iv.constBegin();
304   for (; ivI != iv.constEnd(); ++ivI) {
305     if (!inputVector(*ivI))
306       return false;
307   }
308 
309   //Now, check the inputScalars...
310   QStringList is = inputScalarList();
311   QStringList::ConstIterator isI = is.constBegin();
312   for (; isI != is.constEnd(); ++isI) {
313     if (!inputScalar(*isI))
314       return false;
315   }
316 
317   //Finally, check the inputStrings...
318   QStringList istr = inputStringList();
319   QStringList::ConstIterator istrI = istr.constBegin();
320   for (; istrI != istr.constEnd(); ++istrI) {
321     if (!inputString(*istrI))
322       return false;
323   }
324   return true;
325 }
326 
327 
328 // Register that the outputs have been recalculated.
updateOutput() const329 void BasicPlugin::updateOutput() const {
330   //output vectors...
331   //FIXME: _outputVectors should be used, not this string list!
332   QStringList ov = outputVectorList();
333   QStringList::ConstIterator ovI = ov.constBegin();
334   for (; ovI != ov.constEnd(); ++ovI) {
335     if (VectorPtr o = outputVector(*ovI)) {
336       Q_ASSERT(o->myLockStatus() == KstRWLock::WRITELOCKED);
337       //vectorRealloced(o, o->value(), o->length()); // why here?
338       o->setNewAndShift(o->length(), o->numShift());
339     }
340   }
341 }
342 
descriptionTip() const343 QString BasicPlugin::descriptionTip() const {
344   return tr("Plugin: %1").arg(Name());
345 }
346 
347 }
348 // vim: ts=2 sw=2 et
349