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