33 #include "private/ArnPersist_p.hpp"    38 #include <QtSql/QSqlDatabase>    39 #include <QtSql/QSqlQuery>    40 #include <QtSql/QSqlError>    45 #include <QStringList>    48 #include <QMetaObject>    49 #include <QMetaMethod>    54 ArnItemPersist::ArnItemPersist( 
ArnPersist* arnPersist) :
    60     _arnPersist  = arnPersist;
    63     _storeType   = StoreType::DataBase;
    67 ArnItemPersist::~ArnItemPersist()
    72 void  ArnItemPersist::arnImport( 
const QByteArray& data, 
int ignoreSame)
    74     ArnLinkHandle  handleData;
    75     handleData.flags().set( ArnLinkHandle::Flags::FromPersist);
    80 void  ArnItemPersist::setValue( 
const QByteArray& value, 
int ignoreSame)
    82     ArnLinkHandle  handleData;
    83     handleData.flags().set( ArnLinkHandle::Flags::FromPersist);
    88 ArnVcs::ArnVcs( QObject* parent) :
    99 void  ArnVcs::log( 
int numLog)
   105 void  ArnVcs::files( QString ref)
   111 void  ArnVcs::commit( QString commitMsg, QStringList files, QString name, QString email)
   120 void  ArnVcs::tag( QString name, QString ref)
   127 void  ArnVcs::diff( QString ref, QStringList files)
   134 void  ArnVcs::logRecord( QString ref)
   145 void  ArnVcs::branches()
   150 void  ArnVcs::status()
   155 void  ArnVcs::userSettings()
   160 void  ArnVcs::setUserSettings( QString userName, QString userEmail)
   167 void  ArnVcs::checkout( QString ref, QStringList files)
   175 ArnPersistPrivate::ArnPersistPrivate()
   177     _db            = 
new QSqlDatabase;
   178     _archiveDir    = 
new QDir(
"archive");
   179     _persistDir    = 
new QDir(
"persist");
   181     _sapiCommon    = 
new ArnPersistSapi;
   183     _arnMountPoint = arnNullptr;
   185     _depOffer      = arnNullptr;
   188 ArnPersistPrivate::~ArnPersistPrivate()
   196     if (_arnMountPoint)  
delete _arnMountPoint;
   197     if (_query)  
delete _query;
   198     if (_depOffer)  
delete _depOffer;
   202 void ArnPersist::init()
   206     setupSapi( d->_sapiCommon);
   212     , d_ptr( new ArnPersistPrivate)
   236     d->_persistDir->setPath( path);
   244     d->_archiveDir->setPath( path);
   254         d->_vcs = arnNullptr;
   259     d->_vcs->setParent( 
this);
   261     connect( d->_vcs, SIGNAL(checkoutR()), 
this, SLOT(vcsCheckoutR()));
   263     d->_sapiCommon->batchConnect( d->_vcs, 
ARN_RegExp(
"(.+)"), 
"rq_vcs\\1");
   264     d->_sapiCommon->batchConnect( 
ARN_RegExp(
"^pv_vcs(.+)"), d->_vcs, 
"\\1");
   268 ArnItemPersist*  ArnPersist::getPersistItem( 
const QString& path)
   272     ArnItemPersist*  item = 
new ArnItemPersist( 
this);
   274     uint  linkId = item->linkId();
   276     if (d->_itemPersistMap.contains( linkId)) { 
   277         qDebug() << 
"getPersistItem already persist: path=" << path << 
" link=" << linkId;
   279         item = d->_itemPersistMap.value( linkId);
   284     item->setIgnoreSameValue( 
false);
   285     item->setDelay( 5000);
   287     connect( item->toArnItem(), SIGNAL(changed()), 
this, SLOT(doArnUpdate()));
   288     connect( item->toArnItem(), SIGNAL(arnLinkDestroyed()), 
this, SLOT(doArnDestroy()));
   289     d->_itemPersistMap.insert( linkId, item);
   295 ArnItemPersist*  ArnPersist::setupMandatory( 
const QString& path, 
bool isMandatory)
   299     ArnItemPersist::StoreType  st;
   300     ArnItemPersist*  item = arnNullptr;
   303         item = getPersistItem( path);
   304         item->setMandatory(
true);
   305         if ((item->storeType() == st.DataBase) && !d->_pathPersistMap.contains( path)) {
   306             d->_pathPersistMap.insert( path, item->linkId());
   311         uint  linkId = d->_pathPersistMap.value( path);
   312         if (!linkId)  
return arnNullptr;
   314         item = d->_itemPersistMap.value( linkId);
   316         item->setMandatory(
false);
   317         if (item->storeType() != st.File) {  
   318             d->_pathPersistMap.remove( path);  
   320                 d->_itemPersistMap.remove( linkId);
   329 void  ArnPersist::removeFilePersistItem( 
const QString& path)
   333     uint  linkId = d->_pathPersistMap.value( path);
   336     ArnItemPersist*  item = d->_itemPersistMap.value( linkId);
   338     ArnItemPersist::StoreType  st;
   339     if (item->storeType() != st.File)  
return;  
   341     item->setStoreType( st.DataBase);
   342     setupMandatory( path, item->isMandatory());
   346 void  ArnPersist::doArnDestroy()
   350     ArnItemPersist*  item = ArnItemPersist::fromArnItem( qobject_cast<ArnItem*>( sender()));
   354     d->_itemPersistMap.remove( item->linkId());
   355     d->_pathPersistMap.remove( item->path());
   360 void  ArnPersist::doArnModeChanged( 
const QString& path, uint linkId, 
Arn::ObjectMode mode)
   365     if (!mode.is( mode.
Save))  
return;  
   367     if (d->_itemPersistMap.contains( linkId))  
return;  
   370     ArnItemPersist*  item = getPersistItem( path);
   373     if (getDbValue( path, data, storeId)) {  
   375         item->arnImport( data, 
false);
   376         item->setStoreId( storeId);
   381         QByteArray  data = item->arnExport();
   382         insertDbValue( path, data);
   383         if (getDbId( path, storeId)) {
   384             item->setStoreId( storeId);
   386         item->arnImport( data, 
false);  
   392 void  ArnPersist::doArnUpdate()
   396     ArnItemPersist*  item;
   397     item = ArnItemPersist::fromArnItem( qobject_cast<ArnItem*>( sender()));
   399         ArnM::errorLog( QString(tr(
"Can't get ArnItemPersist sender for doArnUpdate")),
   404     switch (item->storeType()) {
   405     case ArnItemPersist::StoreType::DataBase:
   408         int storeId = item->storeId();
   410             updateDbValue( storeId, item->arnExport());
   413             ArnM::errorLog( QString(tr(
"Can't get persist storeId for doArnUpdate: path=")) +
   418     case ArnItemPersist::StoreType::File:
   422         QFile  file( d->_persistDir->absoluteFilePath( relPath));
   423         file.open( QIODevice::WriteOnly);
   424         QByteArray  data = item->toByteArray();
   438     if (!d->_db->isOpen()) {
   439         ArnM::errorLog( QString(tr(
"DataBase required before mountPoint")),
   444     if (d->_arnMountPoint)  
delete d->_arnMountPoint;
   446     d->_arnMountPoint = 
new ArnItem( 
this);
   447     bool  isOk = d->_arnMountPoint->openFolder( path);
   449         connect( d->_arnMountPoint, SIGNAL(arnModeChanged(QString,uint,
Arn::ObjectMode)),
   456         if (d->_depOffer)  
delete d->_depOffer;
   459         d->_depOffer->advertise(
"$Persist");
   470     if (d->_query)  
delete d->_query;
   472     *d->_db = QSqlDatabase::addDatabase(
"QSQLITE", 
"ArnPersist");
   474     d->_db->setDatabaseName( dbName);
   477     if (!d->_db->open()) {
   478         ArnM::errorLog( QString(tr(
"DataBase open: ") + d->_db->lastError().text()),
   482     d->_query = 
new QSqlQuery( *d->_db);
   484     int  curArnDbVer = 100;  
   486     if (d->_db->tables().contains(
"meta"))
   487         curArnDbVer = metaDbValue(
"ver", 
"101").toInt();
   488     bool  hasStoreTable = d->_db->tables().contains(
"store");
   491     if (curArnDbVer <= 100) {
   492         d->_query->exec(
"CREATE TABLE meta ("   493                      "attr TEXT PRIMARY KEY,"   497     if (curArnDbVer <= 101)
   498         setMetaDbValue(
"ver", 
"102");
   500     if ((curArnDbVer < 200) && hasStoreTable) {
   501         d->_query->exec(
"ALTER TABLE store RENAME TO store_save");
   504     if ((curArnDbVer < 200) || !hasStoreTable) {
   505         d->_query->exec(
"CREATE TABLE store ("   506                      "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"   511                      "isMandatory INTEGER NOT NULL DEFAULT(0),"   512                      "isUsed INTEGER NOT NULL DEFAULT(1))");
   513         setMetaDbValue(
"ver", 
"200");
   516     if ((curArnDbVer < 200) && hasStoreTable) {
   517         d->_query->exec(
"INSERT INTO store (path, value, isUsed, isMandatory) "   518                      "SELECT path, value, isUsed, isMandatory FROM store_save");
   519         d->_query->exec(
"DROP TABLE store_save");
   533     foreach (ArnItemPersist* item, d->_itemPersistMap) {
   534         if (path.isEmpty() || item->path().startsWith( 
fullPath)) {
   537             item->bypassDelayPending();
   544 QString  ArnPersist::metaDbValue( 
const QString& attr, 
const QString& def)
   548     QString  retVal = def;
   550     d->_query->prepare(
"SELECT value FROM meta WHERE attr = :attr");
   551     d->_query->bindValue(
":attr", attr);
   553     if (d->_query->next()) {
   554         retVal = d->_query->value(0).toString();
   564 bool  ArnPersist::setMetaDbValue( 
const QString& attr, 
const QString& value)
   568     QString  curVal = metaDbValue( attr);
   569     if (value == curVal)  
return true;  
   572         d->_query->prepare(
"INSERT INTO meta (attr, value) VALUES (:attr, :value)");
   574         d->_query->prepare(
"UPDATE meta SET value = :value WHERE attr = :attr");
   576     d->_query->bindValue(
":attr", attr);
   577     d->_query->bindValue(
":value", value);
   578     bool  retVal = d->_query->exec();
   585 bool  ArnPersist::getDbId( 
const QString& path, 
int& storeId)
   592     d->_query->prepare(
"SELECT id, isUsed FROM store WHERE path = :path");
   593     d->_query->bindValue(
":path", path);
   595     if (d->_query->next()) {
   596         storeId = d->_query->value(0).toInt();
   597         isUsed  = d->_query->value(1).toInt();
   602     if (!isUsed)  updateDbUsed( storeId, 1);
   610 void  ArnPersist::dbSetupReadValue( 
const QString& meta, 
const QString& valueTxt,
   615     if (!value.isEmpty())  
return;  
   617     if (!meta.isEmpty()) {
   618         d->_xsm->fromXString( meta.toLatin1());
   619         QByteArray  variantType = d->_xsm->value(
"V");
   620         if (!variantType.isEmpty()) {  
   622                   + variantType + 
":" + valueTxt.toUtf8();
   626     value = valueTxt.toUtf8();
   627     if (!value.isEmpty()) {
   628         if (value.at(0) < 32) {  
   638 void ArnPersist::dbSetupWriteValue( QString& meta, QString& valueTxt, QByteArray& value)
   644     if (value.isEmpty())  
return;
   646     uchar  c = uchar( value.at(0));
   648         int  sepPos = value.indexOf(
':', 1);
   649         Q_ASSERT(sepPos > 0);
   651         QByteArray  variantType( value.constData() + 1, sepPos - 1);
   653         d->_xsm->add(
"V", variantType);
   654         meta = QString::fromLatin1( d->_xsm->toXString().constData());
   655         valueTxt = QString::fromUtf8( value.constData() + sepPos + 1, value.size() - sepPos - 1);
   656         value = QByteArray();
   659         valueTxt = QString::fromUtf8( value.constData() + 1, value.size() - 1);
   660         value = QByteArray();
   663         valueTxt = QString::fromUtf8( value.constData(), value.size());
   664         value = QByteArray();
   669 bool  ArnPersist::getDbValue(
int storeId, QString &path, QByteArray &value)
   677     d->_query->prepare(
"SELECT meta, path, valueTxt, value, isUsed FROM store WHERE id = :id");
   678     d->_query->bindValue(
":id", storeId);
   680     if (d->_query->next()) {
   681         meta     = d->_query->value(0).toByteArray();
   682         path     = d->_query->value(1).toString();
   683         valueTxt = d->_query->value(2).toString();
   684         value    = d->_query->value(3).toByteArray();
   685         isUsed   = d->_query->value(4).toInt();
   687         dbSetupReadValue( meta, valueTxt, value);
   691     if (!isUsed)  updateDbUsed( storeId, 1);
   696 bool  ArnPersist::getDbValue( 
const QString& path, QByteArray& value, 
int& storeId)
   704     d->_query->prepare(
"SELECT id, meta, valueTxt, value, isUsed FROM store WHERE path = :path");
   705     d->_query->bindValue(
":path", path);
   707     if (d->_query->next()) {
   708         storeId  = d->_query->value(0).toInt();
   709         meta     = d->_query->value(1).toByteArray();
   710         valueTxt = d->_query->value(2).toString();
   711         value    = d->_query->value(3).toByteArray();
   712         isUsed   = d->_query->value(4).toInt();
   714         dbSetupReadValue( meta, valueTxt, value);
   718     if (!isUsed)  updateDbUsed( storeId, 1);
   723 bool  ArnPersist::getDbMandatoryList( QList<int>& storeIdList)
   729     d->_query->prepare(
"SELECT id FROM store WHERE isMandatory = 1");
   731     while (d->_query->next()) {
   732         storeIdList += d->_query->value(0).toInt();
   741 bool  ArnPersist::getDbList( 
bool isUsed, QList<int> &storeIdList)
   747     d->_query->prepare(
"SELECT id FROM store WHERE isUsed = :isUsed");
   748     d->_query->bindValue(
":isUsed", 
int(isUsed));
   750     while (d->_query->next()) {
   751         storeIdList += d->_query->value(0).toInt();
   760 bool  ArnPersist::insertDbValue( 
const QString& path, 
const QByteArray& value)
   768     QByteArray  value_ = value;
   769     dbSetupWriteValue( meta, valueTxt, value_);
   771     d->_query->prepare(
"INSERT INTO store (meta, path, valueTxt, value) "   772                    "VALUES (:meta, :path, :valueTxt, :value)");
   773     d->_query->bindValue(
":meta", meta);
   774     d->_query->bindValue(
":path", path);
   775     d->_query->bindValue(
":valueTxt", valueTxt);
   776     d->_query->bindValue(
":value", value_);
   777     retVal = d->_query->exec();
   784 bool  ArnPersist::updateDbValue( 
int storeId, 
const QByteArray& value)
   793     QByteArray  value_ = value;
   794     dbSetupWriteValue( meta, valueTxt, value_);
   796     d->_query->prepare(
"UPDATE store SET meta = :meta, valueTxt = :valueTxt, value = :value "   798     d->_query->bindValue(
":id", storeId);
   799     d->_query->bindValue(
":meta", meta);
   800     d->_query->bindValue(
":valueTxt", valueTxt);
   801     d->_query->bindValue(
":value", value_);
   802     retVal = d->_query->exec();
   809 bool  ArnPersist::updateDbUsed( 
int storeId, 
int isUsed)
   816     d->_query->prepare(
"UPDATE store SET isUsed = :isUsed WHERE id = :id");
   817     d->_query->bindValue(
":id", storeId);
   818     d->_query->bindValue(
":isUsed", isUsed);
   819     retVal = d->_query->exec();
   826 bool  ArnPersist::updateDbMandatory( 
int storeId, 
int isMandatory)
   833     d->_query->prepare(
"UPDATE store SET isMandatory = :isMandatory WHERE id = :id");
   834     d->_query->bindValue(
":id", storeId);
   835     d->_query->bindValue(
":isMandatory", isMandatory);
   836     retVal = d->_query->exec();
   850         QDateTime  dateTime = QDateTime::currentDateTime();
   851         QString  nowStr = dateTime.toString(
"yyMMdd-hhmmss");
   852         arFileName = d->_archiveDir->absoluteFilePath( QString(
"persist_%1.db").arg( nowStr));
   855         arFileName = d->_archiveDir->absoluteFilePath( name);
   857     QString  dbFileName = d->_db->databaseName();
   860     return QFile::copy( dbFileName, arFileName);
   864 void  ArnPersist::doLoadMandatory()
   866     QList<int>  mandatoryList;
   867     if (!getDbMandatoryList( mandatoryList))  
return;  
   871     foreach (
int storeId, mandatoryList) {
   872         if (!getDbValue( storeId, path, value))  
continue;  
   874         ArnItemPersist::StoreType  st;
   875         ArnItemPersist*  item = setupMandatory( path, 
true);
   877         if (item->storeType() != st.DataBase)  
continue;  
   881         if (getDbValue( path, data, storeId2)) {
   882             item->arnImport( data, 
false);
   883             item->setStoreId( storeId2);
   886             item->setValue( QByteArray(), 
false);  
   892 void  ArnPersist::doLoadFiles()
   897     getFileList( flist, *d->_persistDir);
   898     foreach (
const QString& relPath, flist) {
   904 void  ArnPersist::loadFile( 
const QString& relPath)
   911     ArnItemPersist*  item;
   912     if (!d->_pathPersistMap.contains( arnPath)) {  
   913         item = getPersistItem( arnPath);
   914         item->setDelay( 500);  
   915         d->_pathPersistMap.insert( arnPath, item->linkId());
   918         uint  linkId = d->_pathPersistMap.value( arnPath);
   919         item = d->_itemPersistMap.value( linkId);
   922     item->setStoreType( ArnItemPersist::StoreType::File);
   924     QFile  file( d->_persistDir->absoluteFilePath( relPath));
   925     file.open( QIODevice::ReadOnly);
   926     QByteArray  data = file.readAll();
   932 void  ArnPersist::getFileList(QStringList& flist, 
const QDir& dir, 
const QDir* baseDir)
   936     QString  path = dir.absolutePath();
   939     foreach( QFileInfo finfo, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files)) {
   940         if (finfo.isFile()) {
   941             flist += baseDir->relativeFilePath( finfo.absoluteFilePath());
   943         else if (finfo.isDir()) {
   944             QString  fname = finfo.fileName();
   945             getFileList( flist, QDir(finfo.absoluteFilePath()), baseDir);
   951 void  ArnPersist::setupSapi( ArnPersistSapi* sapi)
   954     sapi->open( QString(), Mode::Provider);
   955     sapi->batchConnect( 
ARN_RegExp(
"^pv_(.+)"), 
this, 
"sapi\\1", Mode());
   959 void  ArnPersist::destroyRpc()
   969 void  ArnPersist::convertFileList( QStringList& files, 
Arn::NameF nameF)
   971     for (
int i = 0; i < files.size(); ++i) {
   977 void  ArnPersist::vcsCheckoutR()
   984 void  ArnPersist::sapiFlush( 
const QString& path)
   988     bool  isOk = 
flush( path);
   989     emit d->_sapiCommon->rq_flushR( isOk, path);
   993 void  ArnPersist::sapiTest( 
const QString& str, 
int i)
   995     ArnPersistSapi*  sapiSender = qobject_cast<ArnPersistSapi*>( sender());
   997         qDebug() << 
"sapiTest sender=" << sapiSender->pipePath();
   998         sapiSender->sendText(
"sapiTest: str=" + str + 
" int=" + QString::number(i));
  1000     qDebug() << 
"----- sapiTest: str=" << str << 
" int=" << i;
  1004 void  ArnPersist::sapiLoad()
  1010 void  ArnPersist::sapiLs( 
const QString& path)
  1015     getFileList( flist, *d->_persistDir);
  1019         emit d->_sapiCommon->rq_lsR( flist);
  1021         QStringList retList;
  1022         foreach( QString fstr, flist) {
  1023             if (fstr.startsWith( path))
  1026         emit d->_sapiCommon->rq_lsR( retList);
  1031 void  ArnPersist::sapiRm( 
const QString& path)
  1039         getFileList( flist, *d->_persistDir);
  1040         foreach (
const QString& delPath, flist) {
  1041             if (delPath.startsWith( relPath)) {
  1042                 isOk &= d->_persistDir->remove( delPath);
  1051         isOk = d->_persistDir->remove( relPath);
  1052         removeFilePersistItem( path);
  1058     emit d->_sapiCommon->rq_rmR( isOk);
  1062 void  ArnPersist::sapiTouch( 
const QString& path)
  1066     if (path.endsWith(
'/'))  
return;  
  1070     QString  filePath = d->_persistDir->absoluteFilePath( relPath);
  1072     isOk &= d->_persistDir->mkpath( QFileInfo( filePath).dir().path());
  1075     QFile  file( filePath);
  1076     isOk &= file.open( QIODevice::ReadWrite);
  1081     emit d->_sapiCommon->rq_touchR( isOk);
  1085 void  ArnPersist::sapiDbMandatory( 
const QString& path, 
bool isMandatory)
  1092         QList<int>  storeIdList;
  1093         if (!getDbList( 
true, storeIdList)) {
  1094             emit d->_sapiCommon->rq_dbMandatoryR( isOk);
  1100         foreach (
int storeId, storeIdList) {
  1101             if (!getDbValue( storeId, pathDb, value))  
continue;
  1102             if (!pathDb.startsWith( path))  
continue;
  1104             if (updateDbMandatory( storeId, isMandatory)) {
  1105                 setupMandatory( pathDb, isMandatory);
  1113         if (getDbId( path, storeId)) {
  1114             if (updateDbMandatory( storeId, isMandatory)) {
  1115                 setupMandatory( path, isMandatory);
  1121     emit d->_sapiCommon->rq_dbMandatoryR( isOk);
  1125 void  ArnPersist::sapiDbMandatoryLs( 
const QString& path)
  1129     QStringList  retList;
  1130     QList<int>  storeIdList;
  1131     if (!getDbMandatoryList( storeIdList)) {
  1132         emit d->_sapiCommon->rq_dbMandatoryLsR( retList);
  1138     foreach (
int storeId, storeIdList) {
  1139         if (!getDbValue( storeId, pathDb, value))  
continue;
  1140         if (!pathDb.startsWith( path))  
continue;
  1145     emit d->_sapiCommon->rq_dbMandatoryLsR( retList);
  1149 void  ArnPersist::sapiDbLs( 
const QString& path, 
bool isUsed)
  1153     QStringList  retList;
  1154     QList<int>  storeIdList;
  1155     if (!getDbList( isUsed, storeIdList)) {
  1156         emit d->_sapiCommon->rq_dbLsR( retList);
  1162     foreach (
int storeId, storeIdList) {
  1163         if (!getDbValue( storeId, pathDb, value))  
continue;
  1164         if (!pathDb.startsWith( path))  
continue;
  1169     emit d->_sapiCommon->rq_dbLsR( retList);
  1173 void  ArnPersist::sapiDbMarkUnused( 
const QString& path)
  1177     QList<int>  storeIdList;
  1178     if (!getDbList( 
true, storeIdList)) {
  1179         emit d->_sapiCommon->rq_dbMarkUnusedR(
false);  
  1185     foreach (
int storeId, storeIdList) {
  1186         if (!getDbValue( storeId, pathDb, value))  
continue;
  1187         if (!pathDb.startsWith( path))  
continue;
  1189         if (!updateDbUsed( storeId, 
false)) {
  1190             emit d->_sapiCommon->rq_dbMarkUnusedR(
false);  
  1194     emit d->_sapiCommon->rq_dbMarkUnusedR(
true);  
  1198 void  ArnPersist::sapiInfo()
  1202     emit d->_sapiCommon->rq_infoR(
"Arn Persist", 
"1.0");
 
void setValue(const ArnBasicItem &other, int ignoreSame=Arn::SameValue::DefaultAction)
 
ArnPersist(QObject *parent=arnNullptr)
 
Path: "/@/test" ==> "//test", Item: "@" ==> "". 
 
Class for handling persistent Arn Data object. 
 
Class for advertising that a service is available. 
 
Container class with string representation for serialized data. 
 
void setIgnoreSameValue(bool isIgnore=true)
Set skipping of equal value. 
 
void setUncrossed(bool isUncrossed=true)
Set a Bidirectional item as Uncrossed. 
 
QString fullPath(const QString &path)
Convert a path to a full absolute path. 
 
Assigning same value generates an update of the Arn Data Object 
 
void setArchiveDir(const QString &path)
Set the persistent database backup directory. 
 
bool setMountPoint(const QString &path)
Set the persistent enabled tree path. 
 
Only on path, no effect on discrete names. "/test/value" ==> "test/value". 
 
void setVcs(ArnVcs *vcs)
Set the Version Control System to be used. 
 
void arnImport(const QByteArray &data, int ignoreSame=Arn::SameValue::DefaultAction)
Import data to an Arn Data Object 
 
bool setupDataBase(const QString &dbName="persist.db")
Setup the persistent database. 
 
QString convertPath(const QString &path, Arn::NameF nameF)
Convert a path to a specific format. 
 
void setPersistDir(const QString &path)
Set the persistent file directory root 
 
QString parentPath(const QString &path)
Get the parent to a given path 
 
bool doArchive(const QString &name=QString())
Do a persistent database backup. 
 
bool flush(const QString &path=QString())
Save any pending values now. 
 
static void errorLog(QString errText, ArnError err=ArnError::Undef, void *reference=arnNullptr)
 
bool isFolderPath(const QString &path)
Test if path is a folder path 
 
Data is persistent and will be saved. 
 
Handle for an Arn Data Object. 
 
bool isProviderPath(const QString &path)
Test if path is a provider path