src/publishsubscribe/gconflayer_linux.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "gconflayer_linux_p.h"
       
    43 #include <QVariant>
       
    44 
       
    45 QTM_BEGIN_NAMESPACE
       
    46 
       
    47 Q_GLOBAL_STATIC(GConfLayer, gConfLayer);
       
    48 QVALUESPACE_AUTO_INSTALL_LAYER(GConfLayer);
       
    49 
       
    50 GConfLayer::GConfLayer()
       
    51 {
       
    52     GConfItem *gconfItem = new GConfItem("/", true, this);
       
    53     connect(gconfItem, SIGNAL(subtreeChanged(const QString &, const QVariant &)), this, SLOT(notifyChanged(const QString &, const QVariant &)));
       
    54 }
       
    55 
       
    56 GConfLayer::~GConfLayer()
       
    57 {
       
    58     QMutableHashIterator<QString, GConfHandle *> i(m_handles);
       
    59     while (i.hasNext()) {
       
    60         i.next();
       
    61 
       
    62         doRemoveHandle(Handle(i.value()));
       
    63     }
       
    64 }
       
    65 
       
    66 QString GConfLayer::name()
       
    67 {
       
    68     return QLatin1String("GConf Layer");
       
    69 }
       
    70 
       
    71 QUuid GConfLayer::id()
       
    72 {
       
    73     return QVALUESPACE_GCONF_LAYER;
       
    74 }
       
    75 
       
    76 unsigned int GConfLayer::order()
       
    77 {
       
    78     return 0;
       
    79 }
       
    80 
       
    81 QValueSpace::LayerOptions GConfLayer::layerOptions() const
       
    82 {
       
    83     return QValueSpace::PermanentLayer |
       
    84         QValueSpace::WritableLayer;
       
    85 }
       
    86 
       
    87 GConfLayer *GConfLayer::instance()
       
    88 {
       
    89     return gConfLayer();
       
    90 }
       
    91 
       
    92 bool GConfLayer::startup(Type /*type*/)
       
    93 {
       
    94     return true;
       
    95 }
       
    96 
       
    97 bool GConfLayer::value(Handle handle, QVariant *data)
       
    98 {
       
    99     QMutexLocker locker(&m_mutex);
       
   100     GConfHandle *sh = gConfHandle(handle);
       
   101     if (!sh)
       
   102         return false;
       
   103 
       
   104     return getValue(InvalidHandle, sh->path, data);
       
   105 }
       
   106 
       
   107 bool GConfLayer::value(Handle handle, const QString &subPath, QVariant *data)
       
   108 {
       
   109     QMutexLocker locker(&m_mutex);
       
   110     return getValue(handle, subPath, data);
       
   111 }
       
   112 
       
   113 bool GConfLayer::getValue(Handle handle, const QString &subPath, QVariant *data)
       
   114 {
       
   115     if (handle != InvalidHandle && !gConfHandle(handle))
       
   116         return false;
       
   117 
       
   118     QString path(subPath);
       
   119     while (path.endsWith(QLatin1Char('/')))
       
   120         path.chop(1);
       
   121     if (handle != InvalidHandle)
       
   122         while (path.startsWith(QLatin1Char('/')))
       
   123             path = path.mid(1);
       
   124     int index = path.lastIndexOf(QLatin1Char('/'), -1);
       
   125 
       
   126     bool createdHandle = false;
       
   127 
       
   128     QString value;
       
   129     if (index == -1) {
       
   130         value = path;
       
   131     } else {
       
   132         // want a value that is in a sub path under handle
       
   133         value = path.mid(index + 1);
       
   134         path.truncate(index);
       
   135 
       
   136         handle = getItem(handle, path);
       
   137         createdHandle = true;
       
   138     }
       
   139 
       
   140     GConfHandle *sh = gConfHandle(handle);
       
   141     if (!sh)
       
   142         return false;
       
   143 
       
   144     QString fullPath(sh->path);
       
   145     if (fullPath != QLatin1String("/") && !value.isEmpty())
       
   146         fullPath.append(QLatin1Char('/'));
       
   147 
       
   148     fullPath.append(value);
       
   149 
       
   150     GConfItem gconfItem(fullPath);
       
   151     QVariant readValue = gconfItem.value();
       
   152     switch (readValue.type()) {
       
   153     case QVariant::Invalid:
       
   154     case QVariant::Bool:
       
   155     case QVariant::Int:
       
   156     case QVariant::Double:
       
   157     case QVariant::StringList:
       
   158     case QVariant::List:
       
   159         *data = readValue;
       
   160         break;
       
   161     case QVariant::String:
       
   162     {
       
   163         QString readString = readValue.toString();
       
   164         QDataStream readStream(QByteArray::fromBase64(readString.toAscii()));
       
   165         QVariant serializedValue;
       
   166         readStream >> serializedValue;
       
   167         if (serializedValue.isValid()) {
       
   168             *data = serializedValue;
       
   169         } else {
       
   170             *data = readValue;
       
   171         }
       
   172         break;
       
   173     }
       
   174     default:
       
   175         break;
       
   176     }
       
   177 
       
   178     if (createdHandle)
       
   179         doRemoveHandle(handle);
       
   180     return data->isValid();
       
   181 }
       
   182 
       
   183 QSet<QString> GConfLayer::children(Handle handle)
       
   184 {
       
   185     QMutexLocker locker(&m_mutex);
       
   186 
       
   187     GConfHandle *sh = gConfHandle(handle);
       
   188     if (!sh)
       
   189         return QSet<QString>();
       
   190 
       
   191     GConfItem gconfItem(sh->path);
       
   192 
       
   193     QSet<QString> ret;
       
   194     foreach (const QString &child, gconfItem.listEntries() + gconfItem.listDirs()) {
       
   195         const int index = child.lastIndexOf(QLatin1Char('/'), -1);
       
   196         ret += child.mid(index + 1);
       
   197     }
       
   198 
       
   199     return ret;
       
   200 }
       
   201 
       
   202 QAbstractValueSpaceLayer::Handle GConfLayer::item(Handle parent, const QString &subPath)
       
   203 {
       
   204     QMutexLocker locker(&m_mutex);
       
   205     return getItem(parent, subPath);
       
   206 }
       
   207 
       
   208 QAbstractValueSpaceLayer::Handle GConfLayer::getItem(Handle parent, const QString &subPath)
       
   209 {
       
   210     QString fullPath;
       
   211 
       
   212     // Fail on invalid path.
       
   213     if (subPath.isEmpty() || subPath.contains(QLatin1String("//")))
       
   214         return InvalidHandle;
       
   215 
       
   216     if (parent == InvalidHandle) {
       
   217         fullPath = subPath;
       
   218     } else {
       
   219         GConfHandle *sh = gConfHandle(parent);
       
   220         if (!sh)
       
   221             return InvalidHandle;
       
   222 
       
   223         if (subPath == QLatin1String("/")) {
       
   224             fullPath = sh->path;
       
   225         } else if (sh->path.endsWith(QLatin1Char('/')) && subPath.startsWith(QLatin1Char('/')))
       
   226             fullPath = sh->path + subPath.mid(1);
       
   227         else if (!sh->path.endsWith(QLatin1Char('/')) && !subPath.startsWith(QLatin1Char('/')))
       
   228             fullPath = sh->path + QLatin1Char('/') + subPath;
       
   229         else
       
   230             fullPath = sh->path + subPath;
       
   231     }
       
   232 
       
   233     if (m_handles.contains(fullPath)) {
       
   234         GConfHandle *sh = m_handles.value(fullPath);
       
   235         ++sh->refCount;
       
   236         return Handle(sh);
       
   237     }
       
   238 
       
   239     // Create a new handle for path
       
   240     GConfHandle *sh = new GConfHandle(fullPath);
       
   241     m_handles.insert(fullPath, sh);
       
   242 
       
   243     return Handle(sh);
       
   244 }
       
   245 
       
   246 void GConfLayer::setProperty(Handle handle, Properties properties)
       
   247 {
       
   248     QMutexLocker locker(&m_mutex);
       
   249 
       
   250     GConfHandle *sh = gConfHandle(handle);
       
   251     if (!sh)
       
   252         return;
       
   253     QString basePath = sh->path;
       
   254     if (!basePath.endsWith(QLatin1Char('/'))) {
       
   255         basePath += QLatin1Char('/');
       
   256     }
       
   257 
       
   258     if (properties & QAbstractValueSpaceLayer::Publish) {
       
   259         m_monitoringHandles.insert(sh);
       
   260     } else {
       
   261         m_monitoringHandles.remove(sh);
       
   262     }
       
   263 }
       
   264 
       
   265 void GConfLayer::removeHandle(Handle handle)
       
   266 {
       
   267     QMutexLocker locker(&m_mutex);
       
   268     doRemoveHandle(handle);
       
   269 }
       
   270 
       
   271 void GConfLayer::doRemoveHandle(Handle handle)
       
   272 {
       
   273     GConfHandle *sh = gConfHandle(handle);
       
   274     if (!sh)
       
   275         return;
       
   276 
       
   277     if (--sh->refCount)
       
   278         return;
       
   279 
       
   280     m_monitoringHandles.remove(sh);
       
   281     m_handles.remove(sh->path);
       
   282 
       
   283     delete sh;
       
   284 }
       
   285 
       
   286 bool GConfLayer::setValue(QValueSpacePublisher */*creator*/,
       
   287                                     Handle handle,
       
   288                                     const QString &subPath,
       
   289                                     const QVariant &data)
       
   290 {
       
   291     QMutexLocker locker(&m_mutex);
       
   292 
       
   293     GConfHandle *sh = gConfHandle(handle);
       
   294     if (!sh)
       
   295         return false;
       
   296 
       
   297     QString path(subPath);
       
   298     while (path.endsWith(QLatin1Char('/')))
       
   299         path.chop(1);
       
   300 
       
   301     int index = path.lastIndexOf(QLatin1Char('/'), -1);
       
   302 
       
   303     bool createdHandle = false;
       
   304 
       
   305     QString value;
       
   306     if (index == -1) {
       
   307         value = path;
       
   308     } else {
       
   309         // want a value that is in a sub path under handle
       
   310         value = path.mid(index + 1);
       
   311         path.truncate(index);
       
   312 
       
   313         if (path.isEmpty())
       
   314             path.append(QLatin1Char('/'));
       
   315 
       
   316         sh = gConfHandle(getItem(Handle(sh), path));
       
   317         createdHandle = true;
       
   318     }
       
   319 
       
   320     QString fullPath(sh->path);
       
   321     if (fullPath != QLatin1String("/"))
       
   322         fullPath.append(QLatin1Char('/'));
       
   323 
       
   324     fullPath.append(value);
       
   325 
       
   326     GConfItem gconfItem(fullPath);
       
   327     switch (data.type()) {
       
   328     case QVariant::Invalid:
       
   329     case QVariant::Bool:
       
   330     case QVariant::Int:
       
   331     case QVariant::Double:
       
   332     case QVariant::String:
       
   333     case QVariant::StringList:
       
   334     case QVariant::List:
       
   335         gconfItem.set(data);
       
   336         break;
       
   337     default:
       
   338         QByteArray byteArray;
       
   339         QDataStream writeStream(&byteArray, QIODevice::WriteOnly);
       
   340         writeStream << data;
       
   341         QString serializedValue(byteArray.toBase64());
       
   342         gconfItem.set(serializedValue);
       
   343     }
       
   344 
       
   345     if (createdHandle)
       
   346         doRemoveHandle(Handle(sh));
       
   347 
       
   348     return true;
       
   349 }
       
   350 
       
   351 void GConfLayer::sync()
       
   352 {
       
   353     //Not needed
       
   354 }
       
   355 
       
   356 bool GConfLayer::removeSubTree(QValueSpacePublisher * /*creator*/, Handle /*handle*/)
       
   357 {
       
   358     //Not needed
       
   359     return false;
       
   360 }
       
   361 
       
   362 bool GConfLayer::removeValue(QValueSpacePublisher */*creator*/,
       
   363     Handle handle,
       
   364     const QString &subPath)
       
   365 {
       
   366     QMutexLocker locker(&m_mutex);
       
   367 
       
   368     QString fullPath;
       
   369 
       
   370     GConfHandle *sh = gConfHandle(handle);
       
   371     if (!sh)
       
   372         return false;
       
   373 
       
   374     if (handle == InvalidHandle) {
       
   375         fullPath = subPath;
       
   376     } else {
       
   377         if (subPath == QLatin1String("/"))
       
   378             fullPath = sh->path;
       
   379         else if (sh->path.endsWith(QLatin1Char('/')) && subPath.startsWith(QLatin1Char('/')))
       
   380             fullPath = sh->path + subPath.mid(1);
       
   381         else if (!sh->path.endsWith(QLatin1Char('/')) && !subPath.startsWith(QLatin1Char('/')))
       
   382             fullPath = sh->path + QLatin1Char('/') + subPath;
       
   383         else
       
   384             fullPath = sh->path + subPath;
       
   385     }
       
   386 
       
   387     GConfItem gconfItem(fullPath);
       
   388     gconfItem.unset();
       
   389 
       
   390     return true;
       
   391 }
       
   392 
       
   393 void GConfLayer::addWatch(QValueSpacePublisher *, Handle)
       
   394 {
       
   395     //Not needed
       
   396 }
       
   397 
       
   398 void GConfLayer::removeWatches(QValueSpacePublisher *, Handle)
       
   399 {
       
   400     //Not needed
       
   401 }
       
   402 
       
   403 bool GConfLayer::supportsInterestNotification() const
       
   404 {
       
   405     return false;
       
   406 }
       
   407 
       
   408 bool GConfLayer::notifyInterest(Handle, bool)
       
   409 {
       
   410     //Not needed
       
   411     return false;
       
   412 }
       
   413 
       
   414 void GConfLayer::notifyChanged(const QString &key, const QVariant & /*value*/)
       
   415 {
       
   416     foreach (GConfHandle *handle, m_monitoringHandles.values()) {
       
   417         if (key.startsWith(handle->path)) {
       
   418             emit handleChanged(Handle(handle));
       
   419         }
       
   420     }
       
   421 }
       
   422 
       
   423 #include "moc_gconflayer_linux_p.cpp"
       
   424 
       
   425 QTM_END_NAMESPACE