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