00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include "qvpropertyholder.h"
00026
00027 QVPropertyHolder::QVPropertyHolder(const QString name):
00028 name(name), errorString(), variants(), safelyCopiedVariants(), minimum(),
00029 maximum(), _info(), io_flags(), link_flags(), insertion_order(),
00030 inputLinks(), outputLinks()
00031 {
00032 if(qvApp == NULL)
00033 {
00034 QString str = "QVPropertyHolder::QVPropertyHolder(): holder " + name +
00035 ": property holders cannot be created before the " +
00036 "QVApplication instance. Aborting now.";
00037 std::cerr << qPrintable(str) << std::endl;
00038 exit(1);
00039 }
00040 else
00041 qvApp->registerQVPropertyHolder(this);
00042 }
00043
00044 QVPropertyHolder::~QVPropertyHolder()
00045 {
00046 if(qvApp != NULL)
00047 qvApp->deregisterQVPropertyHolder(this);
00048
00049 }
00050
00051 void QVPropertyHolder::setName(const QString name)
00052 { this->name = name; }
00053
00054 const QString QVPropertyHolder::getName() const
00055 { return this->name; }
00056
00057 QList<QString> QVPropertyHolder::getPropertyList() const
00058 { return variants.keys(); }
00059
00060 bool QVPropertyHolder::containsProperty(const QString name) const
00061 { return variants.contains(name); }
00062
00063 QVariant::Type QVPropertyHolder::getPropertyType(const QString name, bool *ok) const
00064 {
00065 if(not checkExists(name,"QVPropertyHolder::getPropertyType()"))
00066 {
00067 if(ok != NULL) *ok = FALSE;
00068 return QVariant::Invalid;
00069 }
00070 if(ok != NULL) *ok = TRUE;
00071 QVariant variant = variants.value(name);
00072 return variant.type();
00073 }
00074
00075 bool QVPropertyHolder::removeProperty(const QString name)
00076 {
00077 if(not checkExists(name,"QVPropertyHolder::removeProperty()"))
00078 return FALSE;
00079 this->variants.remove(name);
00080 this->safelyCopiedVariants.remove(name);
00081 this->minimum.remove(name);
00082 this->maximum.remove(name);
00083 this->_info.remove(name);
00084 this->io_flags.remove(name);
00085 int i = this->insertion_order.indexOf(name);
00086 this->insertion_order.removeAt(i);
00087 return TRUE;
00088 }
00089
00090 bool QVPropertyHolder::setPropertyRange(const QString name, const double & minimum, const double & maximum)
00091 {
00092 if(not checkExists(name,"QVPropertyHolder::setPropertyRange()"))
00093 return FALSE;
00094 if(minimum <= getPropertyValue<double>(name) and
00095 maximum >= getPropertyValue<double>(name))
00096 {
00097 this->minimum[name] = QVariant::fromValue(minimum);
00098 this->maximum[name] = QVariant::fromValue(maximum);
00099 return TRUE;
00100 } else {
00101 QString str = "QVPropertyHolder::setPropertyRange(): property " +
00102 name + " in holder " + getName() + " has value " +
00103 QString("%1").arg(getPropertyValue<double>(name)) +
00104 ", which is not valid for the range [" +
00105 QString("%1,%2").arg(minimum).arg(maximum) + "]." ;
00106 setLastError(str);
00107 if(qvApp->isRunning()) {
00108 std::cerr << qPrintable("Warning: " + str + "\n");
00109 }
00110 return FALSE;
00111 }
00112 }
00113
00114 bool QVPropertyHolder::setPropertyRange(const char *name, int & minimum, int & maximum)
00115 { return setPropertyRange(QString(name), static_cast<double>(minimum), static_cast<double>(maximum)); }
00116
00117 bool QVPropertyHolder::setPropertyRange(QString name, int & minimum, int & maximum)
00118 { return setPropertyRange(name, static_cast<double>(minimum), static_cast<double>(maximum)); }
00119
00120 bool QVPropertyHolder::hasRange(const QString name)
00121 { return maximum.contains(name) and minimum.contains(name); }
00122
00123 bool QVPropertyHolder::isInput(const QString name)
00124 { return (io_flags[name] & inputFlag);};
00125
00126 bool QVPropertyHolder::isOutput(const QString name)
00127 { return (io_flags[name] & outputFlag);};
00128
00129 bool QVPropertyHolder::isLinkedInput(const QString name)
00130 { return (link_flags[name] & linkedInputFlag);};
00131
00132 bool QVPropertyHolder::isLinkedOutput(const QString name)
00133 { return (link_flags[name] & linkedOutputFlag);};
00134
00135 QVariant QVPropertyHolder::getPropertyQVariantValue(const QString name, bool *ok) const
00136 {
00137 if (not checkExists(name,"QVPropertyHolder::getPropertyQVariantValue()"))
00138 if(ok != NULL) *ok = FALSE;
00139 else
00140 if(ok != NULL) *ok = TRUE;
00141 return variants[name];
00142 }
00143
00144 QString QVPropertyHolder::getPropertyInfo(const QString name, bool *ok) const
00145 {
00146 if(not checkExists(name,"QVPropertyHolder::getPropertyInfo()"))
00147 if(ok != NULL) *ok = FALSE;
00148 else
00149 if(ok != NULL) *ok = TRUE;
00150 return this->_info[name];
00151 }
00152
00153 QString QVPropertyHolder::getLastError() const
00154 {
00155 return errorString;
00156 }
00157
00158 const QString QVPropertyHolder::infoInputProperties() const
00159 {
00160 QString info = QString("Input parameters for ") + getName() + QString(":\n");
00161 bool emptyInfo=TRUE;
00162
00163 QStringList props;
00164 QListIterator<QString> i(insertion_order);
00165 while (i.hasNext())
00166 {
00167 QString property = i.next();
00168 if(not (io_flags[property] & inputFlag) or (link_flags[property] & linkedInputFlag))
00169 continue;
00170 emptyInfo=FALSE;
00171 info += " --" + property + "=";
00172 QVariant::Type type = getPropertyType(property);
00173 switch(type)
00174 {
00175 case QVariant::String:
00176 {
00177 READ_PROPERTY(this, QString, property, stringValue);
00178 info += "[text] ";
00179 if(stringValue != QString())
00180 info += "(def. " + stringValue + ") ";
00181 }
00182 break;
00183 case QVariant::Double:
00184 {
00185 READ_PROPERTY(this,double,property,doubleValue);
00186 if(maximum.contains(property) and minimum.contains(property))
00187 {
00188 READ_PROPERTY_MAX(this,double,property,doubleMaximum);
00189 READ_PROPERTY_MIN(this,double,property,doubleMinimum);
00190 info += "[" + QString().setNum(doubleMinimum) + "..."
00191 + QString().setNum(doubleMaximum) + "] ";
00192 }
00193 else
00194 info += "[double] ";
00195 info += "(def. "+ QString().setNum(doubleValue) + ") ";
00196 }
00197 break;
00198 case QVariant::Int:
00199 {
00200 READ_PROPERTY(this,int,property,intValue);
00201 if(maximum.contains(property) and minimum.contains(property))
00202 {
00203 READ_PROPERTY_MAX(this,int,property,intMaximum);
00204 READ_PROPERTY_MIN(this,int,property,intMinimum);
00205 info += "[" + QString().setNum(intMinimum) + "..."
00206 + QString().setNum(intMaximum) + "] ";
00207 }
00208 else
00209 info += "[int] ";
00210 info += "(def. "+ QString().setNum(intValue) + ") ";
00211 }
00212 break;
00213 case QVariant::Bool:
00214 {
00215 READ_PROPERTY(this, bool, property, boolValue);
00216 info += "[true,false]"
00217 + (boolValue ? QString(" (def. true) "):QString("(def. false) "));
00218 }
00219 break;
00220 default:
00221 info += QString("[%1] ").arg(type);
00222 break;
00223 }
00224 QString propertyInfo = getPropertyInfo(property);
00225 if (propertyInfo != QString())
00226 propertyInfo = " " + propertyInfo + ". ";
00227 info += propertyInfo.rightJustified(80-info.split('\n').last().length(),'.') + "\n";
00228 }
00229 if(emptyInfo)
00230 return QString("");
00231
00232 return info;
00233 }
00234
00235 bool QVPropertyHolder::correctRange(const QString name, const double & value) const
00236 {
00237 if(not maximum.contains(name) and not minimum.contains(name))
00238 return TRUE;
00239 double maximum = getPropertyMaximum<double>(name);
00240 double minimum = getPropertyMinimum<double>(name);
00241 if(minimum <= value and maximum >= value)
00242 return TRUE;
00243 else
00244 {
00245 QString str = "QVPropertyHolder::setPropertyValue(): value " +
00246 QString("%1").arg(value) + " for property " +
00247 name + " in holder " + getName() +
00248 "is not valid for the range [" +
00249 QString("%1,%2").arg(minimum).arg(maximum) +
00250 "] stablished for it." ;
00251 setLastError(str);
00252 if(qvApp->isRunning())
00253 {
00254 std::cerr << qPrintable("Warning: " + str + "\n");
00255 }
00256 return FALSE;
00257 }
00258 }
00259
00260 bool QVPropertyHolder::correctRange(const char *name, const int & value) const
00261 { return correctRange(QString(name),static_cast<double>(value)); }
00262
00263 bool QVPropertyHolder::correctRange(QString name, const int & value) const
00264 { return correctRange(name,static_cast<double>(value)); }
00265
00266 bool QVPropertyHolder::checkExists(const QString name, const QString methodname) const
00267 {
00268 if(not variants.contains(name))
00269 {
00270 QString str = methodname + ": property " + name +
00271 " doesn't exists in holder " + getName() + ".";
00272 setLastError(str);
00273 if(qvApp->isRunning()) {
00274 std::cerr << qPrintable("Warning: " + str + "\n");
00275 }
00276 return FALSE;
00277 } else {
00278 return TRUE;
00279 }
00280 }
00281
00282 bool QVPropertyHolder::checkIsNewProperty(const QString name, const QString methodname) const
00283 {
00284 if(variants.contains(name))
00285 {
00286 QString str = methodname + "(): property " + name +
00287 " already exists in holder " + getName() + ".";
00288 setLastError(str);
00289 if(qvApp->isRunning()) {
00290 std::cerr << qPrintable("Warning: " + str + "\n");
00291 }
00292 return FALSE;
00293 } else {
00294 return TRUE;
00295 }
00296 }
00297
00298 bool QVPropertyHolder::linkProperty(QString prop_orig,QVPropertyHolder *qvp_dest,QString prop_dest,LinkType link_type)
00299 {
00300 bool ok1,ok2;
00301 QString errMsg;
00302 QVariant::Type t1,t2;
00303 QVPropertyHolder *qvp_orig=this, *qvp_err=NULL;
00304
00305 t1 = qvp_orig->getPropertyType(prop_orig,&ok1);
00306 t2 = qvp_dest->getPropertyType(prop_dest,&ok2);
00307 if(qvApp->isRunning())
00308 {
00309 qvp_err = qvp_orig;
00310 errMsg = QString("QVPropertyHolder::linkProperty(): Property holder %1:"
00311 "Cannot link properties after launching QVApplication.\n")
00312 .arg(prop_orig).arg(qvp_orig->getName());
00313 }
00314 else if(qvp_orig == qvp_dest)
00315 {
00316 errMsg = QString("QVPropertyHolder::linkProperty(): Property holder %1: cannot link a QVPropertyHolder with itself.\n").arg(qvp_orig->getName());
00317 qvp_err = qvp_orig;
00318 }
00319 else if(not ok1)
00320 {
00321 errMsg = QString("QVPropertyHolder::linkProperty(): Property %1 does not exist in property holder %2.\n")
00322 .arg(prop_orig).arg(qvp_orig->getName());
00323 qvp_err = qvp_orig;
00324 }
00325 else if (not ok2)
00326 {
00327 errMsg = QString("QVPropertyHolder::linkProperty(): Property %1 does not exist in property holder %2.\n")
00328 .arg(prop_dest).arg(qvp_dest->getName());
00329 qvp_err = qvp_dest;
00330 }
00331 else if(t1 != t2)
00332 {
00333 errMsg = QString("QVPropertyHolder::linkProperty(): Properties %1 and %2 of QVPropertyHolders %3 and %4 respectively are not of the same type.\n").arg(prop_orig).arg(prop_dest).arg(qvp_orig->getName()).arg(qvp_dest->getName());
00334 qvp_err = qvp_orig;
00335 }
00336 else if(not (qvp_orig->io_flags[prop_orig] & outputFlag))
00337 {
00338 errMsg = QString("QVPropertyHolder::linkProperty(): Property %1 of property holder %2 is not of Output type, and cannot be linked as such.\n").arg(prop_orig).arg(qvp_orig->getName());
00339 qvp_err = qvp_orig;
00340 }
00341 else if(not (qvp_dest->io_flags[prop_dest] & inputFlag))
00342 {
00343 errMsg = QString("QVPropertyHolder::linkProperty(): Property %1 property holder %2 is not of Input type, and cannot be linked as such.\n").arg(prop_dest).arg(qvp_dest->getName());
00344 qvp_err = qvp_dest;
00345 }
00346
00347 if(errMsg != QString())
00348 {
00349 qvp_err->setLastError(errMsg);
00350 if(qvApp->isRunning()) {
00351 std::cerr << qPrintable("Warning: " + errMsg + "\n");
00352 }
00353 return FALSE;
00354 }
00355 else
00356 {
00357 QVPropertyHolderLink *link = new
00358 QVPropertyHolderLink(qvp_orig,prop_orig,qvp_dest,prop_dest,link_type);
00359 qvp_orig->outputLinks[prop_orig].push_back(link);
00360 qvp_dest->inputLinks[prop_dest] = link;
00361 qvp_dest->link_flags[prop_dest] |= linkedInputFlag;
00362 qvp_orig->link_flags[prop_orig] |= linkedOutputFlag;
00363 return TRUE;
00364 }
00365 }
00366
00367 void QVPropertyHolder::unlink()
00368 {
00369 QMapIterator<QString, QVPropertyHolderLink*> i_in(inputLinks);
00370 while (i_in.hasNext()) {
00371 i_in.next();
00372 QVPropertyHolderLink *link = i_in.value();
00373 link->markedForDeletion = TRUE;
00374
00375
00376 link->SyncSemaphoreIn.release();
00377 }
00378
00379 QMapIterator<QString, QList<QVPropertyHolderLink*> >i_out(outputLinks);
00380 while (i_out.hasNext()) {
00381 i_out.next();
00382 QListIterator<QVPropertyHolderLink*> j_out(i_out.value());
00383 while(j_out.hasNext()) {
00384 QVPropertyHolderLink *link = j_out.next();
00385 link->markedForDeletion = TRUE;
00386
00387
00388 link->SyncSemaphoreOut.release();
00389 }
00390 }
00391 }
00392
00393 void QVPropertyHolder::readInputProperties()
00394 {
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 QMutableMapIterator<QString, QVPropertyHolderLink*> i(inputLinks);
00406 while (i.hasNext()) {
00407 i.next();
00408 QVPropertyHolderLink *link = i.value();
00409 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00410 link->SyncSemaphoreOut.acquire();
00411 }
00412 link->qvp_orig->RWLock.lockForRead();
00413
00414 this->variants[link->prop_dest] = link->qvp_orig->safelyCopiedVariants[link->prop_orig];
00415 link->qvp_orig->RWLock.unlock();
00416 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00417 link->SyncSemaphoreIn.release();
00418 }
00419
00420 if(link->markedForDeletion) {
00421 i.remove();
00422 delete link;
00423 }
00424 }
00425 }
00426
00427 void QVPropertyHolder::writeOutputProperties()
00428 {
00429 QMutableMapIterator<QString, QList<QVPropertyHolderLink*> >i(outputLinks);
00430
00431
00432
00433
00434 while (i.hasNext()) {
00435 i.next();
00436 QListIterator<QVPropertyHolderLink*> j(i.value());
00437 while(j.hasNext()) {
00438 QVPropertyHolderLink *link = j.next();
00439 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00440 link->SyncSemaphoreIn.acquire();
00441 }
00442 }
00443 }
00444
00445
00446
00447 i.toFront();
00448 this->RWLock.lockForWrite();
00449 while (i.hasNext()) {
00450 i.next();
00451 QString prop_orig = i.key();
00452 safelyCopiedVariants[prop_orig] = variants[prop_orig];
00453 }
00454 this->RWLock.unlock();
00455
00456
00457
00458
00459 i.toFront();
00460 while (i.hasNext()) {
00461 i.next();
00462 QMutableListIterator<QVPropertyHolderLink*> j(i.value());
00463 while(j.hasNext()) {
00464 QVPropertyHolderLink *link = j.next();
00465 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00466 link->SyncSemaphoreOut.release();
00467 }
00468
00469 if(link->markedForDeletion) {
00470 j.remove();
00471 delete link;
00472 if(i.value().isEmpty()) {
00473 i.remove();
00474 break;
00475 }
00476 }
00477 }
00478 }
00479 }
00480
00481 void QVPropertyHolder::setLastError(QString str) const
00482 { errorString = str; }
00483
00484 template <> bool QVPropertyHolder::parseArgument<bool>(const QString parameter, const QString value)
00485 {
00486 if (value.toLower() == "true" || value.toLower() == "false")
00487 {
00488
00489 setPropertyValue<bool>(parameter,value.toLower() == "true");
00490 return TRUE;
00491 }
00492 else {
00493 errorString = "QVPropertyHolder::parseArgument(): holder " + getName() +
00494 ": value " + value +
00495 " is not a valid boolean value for parameter " +
00496 parameter + ".\n";
00497 return FALSE;
00498 }
00499 }
00500
00501 template <> bool QVPropertyHolder::parseArgument<int>(const QString parameter, const QString value)
00502 {
00503 bool okInt;
00504 int intValue = value.toInt(&okInt);
00505 if(not okInt)
00506 {
00507 errorString = "QVPropertyHolder::parseArgument(): holder " + getName() +
00508 ": value " + value +
00509 " is not a valid integer value for parameter " +
00510 parameter + ".\n";
00511 return FALSE;
00512 }
00513
00514 setPropertyValue<int>(parameter,intValue);
00515 return TRUE;
00516 }
00517
00518 template <> bool QVPropertyHolder::parseArgument<double>(const QString parameter, const QString value)
00519 {
00520 bool okDouble;
00521 double doubleValue = value.toDouble(&okDouble);
00522 if(not okDouble)
00523 {
00524 errorString = "QVPropertyHolder::parseArgument(): holder " + getName() +
00525 ": value " + value +
00526 " is not a valid double value for parameter " +
00527 parameter + ".\n";
00528 return FALSE;
00529 }
00530
00531 setPropertyValue<double>(parameter,doubleValue);
00532 return TRUE;
00533 }
00534
00535 template <> bool QVPropertyHolder::parseArgument<QString>(const QString parameter, const QString value)
00536 {
00537
00538 setPropertyValue<QString>(parameter,value);
00539 return TRUE;
00540 }