00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <QVDisjointSet>
00026 #include <QVPropertyContainer>
00027
00028 uint QVPropertyContainer::maxIdent = 0;
00029
00030
00031 QVPropertyContainer::QVPropertyContainer(const QString name):
00032 name(name), errorString(), variants(), safelyCopiedVariants(), minimum(),
00033 maximum(), _info(), io_flags(), link_flags(), insertion_order(),
00034 inputLinks(), outputLinks()
00035 {
00036 ident = getNewIdent();
00037 qDebug() << "QVPropertyContainer::QVPropertyContainer(" << name << ")";
00038 if(qvApp == NULL)
00039 {
00040 QString str = "QVPropertyContainer::QVPropertyContainer(): holder " + name +
00041 ": property holders cannot be created before the " +
00042 "QVApplication instance. Aborting now.";
00043 std::cerr << qPrintable(str) << std::endl;
00044 exit(1);
00045 }
00046 else
00047 {
00048 qvApp->registerQVPropertyContainer(this);
00049
00050 }
00051 qDebug() << "QVPropertyContainer::QVPropertyContainer(" << name << ") <- return";
00052 }
00053
00054 QVPropertyContainer::QVPropertyContainer(const QVPropertyContainer &cont):
00055 name(cont.name), ident(cont.ident), errorString(cont.errorString), variants(cont.variants),
00056 safelyCopiedVariants(cont.safelyCopiedVariants), minimum(cont.minimum), maximum(cont.maximum),
00057 _info(cont._info), io_flags(cont.io_flags), link_flags(cont.link_flags), insertion_order(cont.insertion_order),
00058 RWLock(), inputLinks(cont.inputLinks), outputLinks(cont.outputLinks)
00059 {
00060 qDebug() << "QVPropertyContainer::QVPropertyContainer(" << name << ")";
00061 if(qvApp == NULL)
00062 {
00063 QString str = "QVPropertyContainer::QVPropertyContainer(): holder " + name +
00064 ": property holders cannot be created before the " +
00065 "QVApplication instance. Aborting now.";
00066 std::cerr << qPrintable(str) << std::endl;
00067 exit(1);
00068 }
00069 else
00070 {
00071 qvApp->registerQVPropertyContainer(this);
00072
00073 }
00074 qDebug() << "QVPropertyContainer::QVPropertyContainer(" << name << ") <- return";
00075 }
00076
00077 QVPropertyContainer & QVPropertyContainer::operator=(const QVPropertyContainer &cont)
00078 {
00079 name = cont.name;
00080 ident = cont.ident;
00081 errorString = cont.errorString;
00082 variants = cont.variants;
00083 safelyCopiedVariants = cont.safelyCopiedVariants;
00084 minimum = cont.minimum;
00085 maximum = cont.maximum;
00086 _info = cont._info;
00087 io_flags = cont.io_flags;
00088 link_flags = cont.link_flags;
00089 insertion_order = cont.insertion_order;
00090 inputLinks = cont.inputLinks;
00091 outputLinks = cont.outputLinks;
00092
00093 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::All));
00094 return *this;
00095 }
00096
00097 QVPropertyContainer::~QVPropertyContainer()
00098 {
00099 if(qvApp != NULL)
00100 qvApp->deregisterQVPropertyContainer(this);
00102 unlink();
00103 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::ContainerDel));
00104 }
00105
00106 void QVPropertyContainer::setName(const QString name)
00107 { this->name = name; informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::Name)); }
00108
00109 const QString QVPropertyContainer::getName() const
00110 { return this->name; }
00111
00112 const uint QVPropertyContainer::getId() const
00113 { return this->ident; }
00114
00115 bool QVPropertyContainer::operator==(const QVPropertyContainer &cont) const
00116 { return (ident == cont.ident); }
00117
00118 QList<QString> QVPropertyContainer::getPropertyList() const
00119 { return variants.keys(); }
00120
00121 bool QVPropertyContainer::containsProperty(const QString name) const
00122 { return variants.contains(name); }
00123
00124 int QVPropertyContainer::getPropertyType(const QString name, bool *ok) const
00125 {
00126 if(not checkExists(name,"QVPropertyContainer::getPropertyType()"))
00127 {
00128 if(ok != NULL) *ok = FALSE;
00129 return QVariant::Invalid;
00130 }
00131 if(ok != NULL) *ok = TRUE;
00132 QVariant variant = variants.value(name);
00133 return variant.userType();
00134 }
00135
00136 bool QVPropertyContainer::removeProperty(const QString name)
00137 {
00138 if(not checkExists(name,"QVPropertyContainer::removeProperty()"))
00139 return FALSE;
00140 this->variants.remove(name);
00141 this->safelyCopiedVariants.remove(name);
00142 this->minimum.remove(name);
00143 this->maximum.remove(name);
00144 this->_info.remove(name);
00145 this->io_flags.remove(name);
00146 int i = this->insertion_order.indexOf(name);
00147 this->insertion_order.removeAt(i);
00148 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::PropertyDel, name));
00149 return TRUE;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 bool QVPropertyContainer::hasRange(const QString name) const
00181 { return maximum.contains(name) and minimum.contains(name); }
00182
00183 bool QVPropertyContainer::isInput(const QString name) const
00184 { return (io_flags[name] & inputFlag);};
00185
00186 bool QVPropertyContainer::isOutput(const QString name) const
00187 { return (io_flags[name] & outputFlag);};
00188
00189 bool QVPropertyContainer::isGUIInvisible(const QString name) const
00190 { return (io_flags[name] & guiInvisible);};
00191
00192 bool QVPropertyContainer::isLinkedInput(const QString name) const
00193 { return (link_flags[name] & linkedInputFlag);};
00194
00195 bool QVPropertyContainer::isLinkedOutput(const QString name) const
00196 { return (link_flags[name] & linkedOutputFlag);};
00197
00198 QVariant QVPropertyContainer::getPropertyQVariantValue(const QString name, bool *ok) const
00199 {
00200 if (not checkExists(name,"QVPropertyContainer::getPropertyQVariantValue()"))
00201 if(ok != NULL) *ok = FALSE;
00202 else
00203 if(ok != NULL) *ok = TRUE;
00204 return variants[name];
00205 }
00206
00207 QString QVPropertyContainer::getPropertyInfo(const QString name, bool *ok) const
00208 {
00209 if(not checkExists(name,"QVPropertyContainer::getPropertyInfo()"))
00210 if(ok != NULL) *ok = FALSE;
00211 else
00212 if(ok != NULL) *ok = TRUE;
00213 return this->_info[name];
00214 }
00215
00216 QString QVPropertyContainer::getLastError() const
00217 {
00218 return errorString;
00219 }
00220
00221 const QString QVPropertyContainer::infoInputProperties() const
00222 {
00223 qDebug() << "QVPropertyContainer::infoInputProperties(" << getName() << ")";
00224
00225 QString info = QString("Input parameters for ") + getName() + QString(":\n");
00226 bool emptyInfo=TRUE;
00227
00228 qDebug() << "QVPropertyContainer::infoInputProperties(): Properties " << insertion_order;
00229
00230 foreach (QString property, insertion_order)
00231
00232
00233 {
00234
00235
00236 if( not isInput(property) )
00237 continue;
00238
00239 bool printableProperty = TRUE;
00240 QString propertyInfo(" --" + property + "=");
00241
00242 switch(getPropertyType(property))
00243 {
00244 case QVariant::String:
00245 propertyInfo += QString() + "[text] " + "(def. '" + getPropertyValue<QString>(property) + "') ";
00246 break;
00247
00248 case QVariant::Double:
00249 propertyInfo += ( (maximum.contains(property) and minimum.contains(property))?
00250 "[" + QString().setNum(getPropertyMinimum<double>(property)) + "..."
00251 + QString().setNum(getPropertyMaximum<double>(property)) + "] ":
00252 "[double] " ) + "(def. "+ QString().setNum(getPropertyValue<double>(property)) + ") ";
00253 break;
00254
00255 case QVariant::Int:
00256 propertyInfo += ( (maximum.contains(property) and minimum.contains(property))?
00257 "[" + QString().setNum(getPropertyMinimum<int>(property)) + "..." +
00258 QString().setNum(getPropertyMaximum<int>(property)) + "] ":
00259 "[int] " ) + "(def. "+ QString().setNum(getPropertyValue<int>(property)) + ") ";
00260 break;
00261
00262 case QVariant::Bool:
00263 propertyInfo += "[true,false]" + (getPropertyValue<bool>(property) ?
00264 QString(" (def. true) "):QString("(def. false) "));
00265 break;
00266
00267 default:
00268 printableProperty = FALSE;
00269 break;
00270 }
00271
00272 if (printableProperty)
00273 {
00274 info += propertyInfo + getPropertyInfo(property).rightJustified(100-propertyInfo.split('\n').last().length(),' ') + ".\n";
00275 emptyInfo=FALSE;
00276 }
00277 }
00278
00279 qDebug() << "QVPropertyContainer::infoInputProperties(" << getName() << ") <~ return";
00280
00281 if(emptyInfo)
00282 return QString("");
00283
00284 return info;
00285 }
00286
00287 bool QVPropertyContainer::correctRange(const QString name, const double & value) const
00288 {
00289 if(not maximum.contains(name) and not minimum.contains(name))
00290 return TRUE;
00291 double maximum = getPropertyMaximum<double>(name);
00292 double minimum = getPropertyMinimum<double>(name);
00293 if(minimum <= value and maximum >= value)
00294 return TRUE;
00295 else
00296 {
00297 QString str = "QVPropertyContainer::setPropertyValue(): value " +
00298 QString("%1").arg(value) + " for property " +
00299 name + " in holder " + getName() +
00300 "is not valid for the range [" +
00301 QString("%1,%2").arg(minimum).arg(maximum) +
00302 "] stablished for it." ;
00303 setLastError(str);
00304 if(qvApp->isRunning())
00305 {
00306 std::cerr << qPrintable("Warning: " + str + "\n");
00307 }
00308 return FALSE;
00309 }
00310 }
00311
00312 bool QVPropertyContainer::correctRange(const char *name, const int & value) const
00313 { return correctRange(QString(name),static_cast<double>(value)); }
00314
00315 bool QVPropertyContainer::correctRange(QString name, const int & value) const
00316 { return correctRange(name,static_cast<double>(value)); }
00317
00318 bool QVPropertyContainer::checkExists(const QString name, const QString methodname) const
00319 {
00320 if(not variants.contains(name))
00321 {
00322 QString str = methodname + ": property " + name +
00323 " doesn't exists in holder " + getName() + ".";
00324 setLastError(str);
00325 if(qvApp->isRunning()) {
00326 std::cerr << qPrintable("Warning: " + str + "\n");
00327 }
00328 return FALSE;
00329 } else {
00330 return TRUE;
00331 }
00332 }
00333
00334 bool QVPropertyContainer::checkIsNewProperty(const QString name, const QString methodname) const
00335 {
00336 if(variants.contains(name))
00337 {
00338 QString str = methodname + "(): property " + name +
00339 " already exists in holder " + getName() + ".";
00340 setLastError(str);
00341 if(qvApp->isRunning()) {
00342 std::cerr << qPrintable("Warning: " + str + "\n");
00343 }
00344 return FALSE;
00345 } else {
00346 return TRUE;
00347 }
00348 }
00349
00350 bool QVPropertyContainer::linkProperty(QString prop_orig, QVPropertyContainer *qvp_dest, QString prop_dest, LinkType link_type)
00351 {
00352 bool ok1,ok2;
00353 QString errMsg;
00354 int t1,t2;
00355 QVPropertyContainer *qvp_err=NULL;
00356
00357 t1 = this->getPropertyType(prop_orig,&ok1);
00358 t2 = qvp_dest->getPropertyType(prop_dest,&ok2);
00359 if(qvApp->isRunning())
00360 {
00361 qvp_err = this;
00362 errMsg = QString("QVPropertyContainer::linkProperty(): Property holder %1:"
00363 "Cannot link properties after launching QVApplication.\n")
00364 .arg(prop_orig).arg(this->getName());
00365 }
00366 else if(this == qvp_dest)
00367 {
00368 errMsg = QString("QVPropertyContainer::linkProperty(): Property holder %1: cannot link a QVPropertyContainer with itself.\n").arg(this->getName());
00369 qvp_err = this;
00370 }
00371 else if(not ok1)
00372 {
00373 errMsg = QString("QVPropertyContainer::linkProperty(): Property %1 does not exist in property holder %2.\n")
00374 .arg(prop_orig).arg(this->getName());
00375 qvp_err = this;
00376 }
00377 else if (not ok2)
00378 {
00379 errMsg = QString("QVPropertyContainer::linkProperty(): Property %1 does not exist in property holder %2.\n")
00380 .arg(prop_dest).arg(qvp_dest->getName());
00381 qvp_err = qvp_dest;
00382 }
00383 else if(t1 != t2)
00384 {
00385 errMsg = QString("QVPropertyContainer::linkProperty(): Properties %1 and %2 of QVPropertyContainers %3 and %4 respectively are not of the same type.\n").arg(prop_orig).arg(prop_dest).arg(this->getName()).arg(qvp_dest->getName());
00386 qvp_err = this;
00387 }
00388 else if(not (this->io_flags[prop_orig] & outputFlag))
00389 {
00390 errMsg = QString("QVPropertyContainer::linkProperty(): Property %1 of property holder %2 is not of Output type, and cannot be linked as such.\n").arg(prop_orig).arg(this->getName());
00391 qvp_err = this;
00392 }
00393 else if(not (qvp_dest->io_flags[prop_dest] & inputFlag))
00394 {
00395 errMsg = QString("QVPropertyContainer::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());
00396 qvp_err = qvp_dest;
00397 }
00398
00399 if(errMsg != QString())
00400 {
00401 qvp_err->setLastError(errMsg);
00402 if(qvApp->isRunning()) {
00403 std::cerr << qPrintable("Warning: " + errMsg + "\n");
00404 }
00405 return FALSE;
00406 }
00407 else
00408 {
00409 QVPropertyContainerLink *link = new QVPropertyContainerLink(this,prop_orig,qvp_dest,prop_dest,link_type);
00410 this->outputLinks[prop_orig].push_back(link);
00411 this->link_flags[prop_orig] |= linkedOutputFlag;
00412
00413
00414
00415 qvp_dest->addInputLink(prop_dest, link);
00416
00417
00418
00419 this->RWLock.lockForWrite();
00420 safelyCopiedVariants[prop_orig] = variants[prop_orig];
00421 this->RWLock.unlock();
00422
00423 if (link_type == QVPropertyContainer::AsynchronousLink)
00424 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::LinkAdd, this->getName(), prop_orig, qvp_dest->getName(), prop_dest,FALSE));
00425 else
00426 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::LinkAdd, this->getName(), prop_orig, qvp_dest->getName(), prop_dest,TRUE));
00427 return TRUE;
00428 }
00429 }
00430
00431 void QVPropertyContainer::addInputLink(QString prop_dest, QVPropertyContainerLink *link)
00432 {
00433 inputLinks[prop_dest] = link;
00434 link_flags[prop_dest] |= linkedInputFlag;
00435 }
00436
00437 void QVPropertyContainer::linkProperty(QVPropertyContainer *container, LinkType linkType)
00438 {
00439 QList<QString> localProper = getPropertyList();
00440 QList<QString> inputProper = container->getPropertyList();
00441
00442 qSort(localProper.begin(), localProper.end());
00443 qSort(inputProper.begin(), inputProper.end());
00444
00445 int i=0, l=0;
00446 while ( (i < inputProper.size()) && (l < localProper.size()) )
00447 {
00448 QString localName = localProper[l];
00449 QString inputName = inputProper[i];
00450 if (
00451 (localName == inputName) &&
00452 (getPropertyType(localName) == container->getPropertyType(inputName)) &&
00453 (io_flags[localName] & outputFlag) &&
00454 (container->io_flags[inputName] & inputFlag) &&
00455 (!(io_flags[localName] & internalProp)) &&
00456 (!(container->io_flags[inputName] & internalProp))
00457 )
00458 linkProperty(localProper[l], container, inputProper[i], linkType);
00459
00460 if(localName <= inputName) l++;
00461 if(localName >= inputName) i++;
00462 }
00463 }
00464
00465 bool QVPropertyContainer::unlinkProperty(QString origName, QVPropertyContainer *destCont, QString destName)
00466 {
00467 QList<QVPropertyContainerLink*> linkList = outputLinks[origName];
00468 foreach(QVPropertyContainerLink* link, linkList) {
00469 if ( (link->qvp_orig == this) && (link->prop_orig == origName) &&
00470 (link->qvp_dest == destCont) && (link->prop_dest == destName) ) {
00471 link->markedForDeletion = TRUE;
00472
00473
00474 link->SyncSemaphoreOut.release();
00475 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::LinkDel, this->getName(), origName, destCont->getName(), destName));
00476 return TRUE;
00477 }
00478 }
00479 return FALSE;
00480 }
00481
00482 void QVPropertyContainer::unlink()
00483 {
00484 foreach(QVPropertyContainerLink* link, inputLinks.values()) {
00485 link->markedForDeletion = TRUE;
00486
00487
00488 link->SyncSemaphoreIn.release();
00489
00490 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::LinkDel, link->qvp_orig_name, link->prop_orig, link->qvp_dest_name, link->prop_dest));
00491 }
00492
00493 foreach(QList<QVPropertyContainerLink*> linkList, outputLinks.values()) {
00494 foreach(QVPropertyContainerLink* link, linkList) {
00495 link->markedForDeletion = TRUE;
00496
00497
00498 link->SyncSemaphoreOut.release();
00499
00500 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::LinkDel, link->qvp_orig_name, link->prop_orig, link->qvp_dest_name, link->prop_dest));
00501 }
00502 }
00503 }
00504
00505 void QVPropertyContainer::readInputProperties()
00506 {
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 QMutableMapIterator<QString, QVPropertyContainerLink*> i(inputLinks);
00518 while (i.hasNext()) {
00519 i.next();
00520 QVPropertyContainerLink *link = i.value();
00521 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00522 link->SyncSemaphoreOut.acquire();
00523 }
00524 link->qvp_orig->RWLock.lockForRead();
00525
00526 this->variants[link->prop_dest] = link->qvp_orig->safelyCopiedVariants[link->prop_orig];
00527 link->qvp_orig->RWLock.unlock();
00528 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00529 link->SyncSemaphoreIn.release();
00530 }
00531 informer.emitChange(QVPropertyContainerChange(this, QVPropertyContainerChange::PropertyValue, link->prop_dest));
00532
00533 if(link->markedForDeletion) {
00534 i.remove();
00535 toDeleteLink(link);
00536 }
00537 }
00538 }
00539
00540 void QVPropertyContainer::writeOutputProperties()
00541 {
00542 QMutableMapIterator<QString, QList<QVPropertyContainerLink*> >i(outputLinks);
00543
00544
00545
00546
00547 while (i.hasNext()) {
00548 i.next();
00549 QListIterator<QVPropertyContainerLink*> j(i.value());
00550 while(j.hasNext()) {
00551 QVPropertyContainerLink *link = j.next();
00552 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00553 link->SyncSemaphoreIn.acquire();
00554 }
00555 }
00556 }
00557
00558
00559
00560 i.toFront();
00561 this->RWLock.lockForWrite();
00562 while (i.hasNext()) {
00563 i.next();
00564 QString prop_orig = i.key();
00565 safelyCopiedVariants[prop_orig] = variants[prop_orig];
00566 }
00567 this->RWLock.unlock();
00568
00569
00570
00571
00572 i.toFront();
00573 while (i.hasNext()) {
00574 i.next();
00575 QMutableListIterator<QVPropertyContainerLink*> j(i.value());
00576 while(j.hasNext()) {
00577 QVPropertyContainerLink *link = j.next();
00578 if(link->link_type == SynchronousLink and not link->markedForDeletion) {
00579 link->SyncSemaphoreOut.release();
00580 }
00581
00582 if(link->markedForDeletion) {
00583 j.remove();
00584 toDeleteLink(link);
00585 if(i.value().isEmpty()) {
00586 i.remove();
00587 break;
00588 }
00589 }
00590 }
00591 }
00592 }
00593
00594 void QVPropertyContainer::toDeleteLink(QVPropertyContainerLink* link)
00595 {
00596 if (link->qvp_orig == this) {
00597 link->qvp_orig = NULL;
00598 }
00599 else if (link->qvp_dest == this) {
00600 link->qvp_dest = NULL;
00601 }
00602
00603 if ((link->qvp_orig == NULL) && (link->qvp_dest == NULL)) delete link;
00604 }
00605
00606 void QVPropertyContainer::setLastError(QString str) const
00607 { errorString = str; }
00608
00609 bool QVPropertyContainer::areSynchronized(const QList<QVPropertyContainer *> conts)
00610 {
00611 QVDisjointSet dSet(conts.size());
00612
00613 for (int i = 0; i < conts.size(); i++)
00614 for (int j = i+1; j < conts.size(); j++)
00615 {
00616 bool find = false;
00617
00618 if (conts.at(i)->getId() == conts.at(j)->getId())
00619 {
00620 dSet.unify(i, j);
00621 find = true;
00622 }
00623 if (!find)
00624 {
00625 const QMap<QString, QVPropertyContainerLink* > inLinksI = conts.at(i)->getInputLinks();
00626 foreach(QVPropertyContainerLink* proConLink, inLinksI.values())
00627 if ( (proConLink->qvp_orig->getId() == conts.at(j)->getId()) &&
00628 (proConLink->link_type == SynchronousLink) )
00629 {
00630 dSet.unify(i, j);
00631 find = true;
00632 break;
00633 }
00634 }
00635 if (!find)
00636 {
00637 const QMap<QString, QVPropertyContainerLink* > inLinksJ = conts.at(j)->getInputLinks();
00638 foreach(QVPropertyContainerLink* proConLink, inLinksJ.values())
00639 if ( (proConLink->qvp_orig->getId() == conts.at(i)->getId()) &&
00640 (proConLink->link_type == SynchronousLink) )
00641 {
00642 dSet.unify(i, j);
00643 break;
00644 }
00645 }
00646 }
00647
00648 return (dSet.numberOfSets() == 1);
00649 }
00650
00651 template <> bool QVPropertyContainer::parseArgument<bool>(const QString parameter, const QString value)
00652 {
00653 if (value.toLower() == "true" || value.toLower() == "false")
00654 {
00655
00656 setPropertyValue<bool>(parameter,value.toLower() == "true");
00657 return TRUE;
00658 }
00659 else {
00660 errorString = "QVPropertyContainer::parseArgument(): holder " + getName() +
00661 ": value " + value +
00662 " is not a valid boolean value for parameter " +
00663 parameter + ".\n";
00664 return FALSE;
00665 }
00666 }
00667
00668 template <> bool QVPropertyContainer::parseArgument<int>(const QString parameter, const QString value)
00669 {
00670 bool okInt;
00671 int intValue = value.toInt(&okInt);
00672 if(not okInt)
00673 {
00674 errorString = "QVPropertyContainer::parseArgument(): holder " + getName() +
00675 ": value " + value +
00676 " is not a valid integer value for parameter " +
00677 parameter + ".\n";
00678 return FALSE;
00679 }
00680
00681 setPropertyValue<int>(parameter,intValue);
00682 return TRUE;
00683 }
00684
00685 template <> bool QVPropertyContainer::parseArgument<double>(const QString parameter, const QString value)
00686 {
00687 bool okDouble;
00688 double doubleValue = value.toDouble(&okDouble);
00689 if(not okDouble)
00690 {
00691 errorString = "QVPropertyContainer::parseArgument(): holder " + getName() +
00692 ": value " + value +
00693 " is not a valid double value for parameter " +
00694 parameter + ".\n";
00695 return FALSE;
00696 }
00697
00698 setPropertyValue<double>(parameter,doubleValue);
00699 return TRUE;
00700 }
00701
00702 template <> bool QVPropertyContainer::parseArgument<QString>(const QString parameter, const QString value)
00703 {
00704
00705 setPropertyValue<QString>(parameter,value);
00706 return TRUE;
00707 }