src/versit/qversitproperty.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
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 "qversitproperty.h"
       
    43 #include "qversitproperty_p.h"
       
    44 #include "qmobilityglobal.h"
       
    45 
       
    46 #include <QStringList>
       
    47 #include <QTextCodec>
       
    48 
       
    49 QTM_BEGIN_NAMESPACE
       
    50 
       
    51 /*!
       
    52   \class QVersitProperty
       
    53   \brief The QVersitProperty class stores the name, value, groups and parameters of a Versit property.
       
    54   \ingroup versit
       
    55 
       
    56   A vCard is represented in abstract form as a QVersitDocument that consists of a number of
       
    57   properties such as a name (N), a telephone number (TEL) and an email address (EMAIL), for
       
    58   instance.  Each of these properties is stored as an instance of a QVersitProperty in a
       
    59   QVersitDocument.
       
    60 
       
    61   A QVersitProperty consists of a list of groups, a name, a list of parameters (key/value pairs),
       
    62   and a value.
       
    63 
       
    64   The value of a QVersitProperty is stored as a QVariant and should always be one of four types:
       
    65   QString for textual values, QByteArray for binary data (eg. images), QStringList for structured
       
    66   textual data, or QVersitDocument for nested documents.  The \l QVersitReader will parse Versit
       
    67   properties and assign the correct type of object to the property value.  The \l QVersitWriter will
       
    68   serialize objects of these types correctly into the (text-based) Versit format.
       
    69 
       
    70   For example, a property might appear in a vCard as:
       
    71   \code
       
    72   ADR;TYPE=home,postal:;;123 Main Street;Any Town;CA;91921-1234
       
    73   \endcode
       
    74   This would be stored as a QVersitProperty with the name \tt{ADR} and two parameters (both named
       
    75   \tt{TYPE} and with values \tt{home} and \tt{postal} respectively.  The value of the
       
    76   QVersitProperty is a QStringList with six strings, and the valueType is CompoundType.
       
    77 
       
    78   QVersitProperty supports implicit sharing.  The property name and parameter names of a
       
    79   QVersitProperty are converted to upper-case when they are stored to a QVersitProperty.
       
    80 
       
    81   \sa QVersitDocument
       
    82  */
       
    83 
       
    84 /*!
       
    85   \enum QVersitProperty::ValueType
       
    86   Describes the type of data held in the property's value.
       
    87 
       
    88   The vCard and iCalendar specifications allows a property value to hold a string, binary data, or a
       
    89   nested document.  String values can either be unstructured or structured.  Structured strings can
       
    90   be either of compound type or list type.  A compound value is one that is delimited by semicolons,
       
    91   allows empty components, and has a property-specific cardinality and ordering.  A list value is
       
    92   one that is delimited by commas, does not have empty components, and has no restrictions on
       
    93   cardinality or ordering.
       
    94 
       
    95   \value PlainType The property value holds an unstructured string and can be retrieved with
       
    96   QVersitProperty::value()
       
    97   \value CompoundType The property value holds a compound string and can be retrieved with
       
    98   QVersitProperty::value<QStringList>()
       
    99   \value ListType The property value holds a list of strings and can be retrieved with
       
   100   QVersitProperty::value<QStringList>()
       
   101   \value BinaryType The property value holds a binary value and can be retrieved with
       
   102   QVersitProperty::value<QByteArray>()
       
   103   \value VersitDocumentType The property value holds a nested Versit document and can be retrieved
       
   104   with QVersitProperty::value<QVersitDocument>()
       
   105  */
       
   106 
       
   107 /*! Constructs a new empty property */
       
   108 QVersitProperty::QVersitProperty() : d(new QVersitPropertyPrivate())
       
   109 {
       
   110 }
       
   111 
       
   112 /*! Constructs a property that is a copy of \a other */
       
   113 QVersitProperty::QVersitProperty(const QVersitProperty& other) : d(other.d)
       
   114 {
       
   115 }
       
   116 
       
   117 /*! Frees the memory used by the property */
       
   118 QVersitProperty::~QVersitProperty()
       
   119 {
       
   120 }
       
   121 
       
   122 /*! Assigns this property to \a other */
       
   123 QVersitProperty& QVersitProperty::operator=(const QVersitProperty& other)
       
   124 {
       
   125     if (this != &other)
       
   126         d = other.d;
       
   127     return *this;
       
   128 }
       
   129 
       
   130 /*! Returns true if this is equal to \a other; false otherwise. */
       
   131 bool QVersitProperty::operator==(const QVersitProperty& other) const
       
   132 {
       
   133     bool equal = d->mGroups == other.d->mGroups &&
       
   134             d->mName == other.d->mName &&
       
   135             d->mParameters == other.d->mParameters &&
       
   136             d->mValueType == other.d->mValueType;
       
   137     if (!equal)
       
   138         return false;
       
   139 
       
   140     // QVariant doesn't support == on QVersitDocuments - do it manually
       
   141     if (d->mValue.userType() == qMetaTypeId<QVersitDocument>())
       
   142         return  other.d->mValue.userType() == qMetaTypeId<QVersitDocument>()
       
   143             && d->mValue.value<QVersitDocument>() == other.d->mValue.value<QVersitDocument>();
       
   144     else
       
   145         return d->mValue == other.d->mValue;
       
   146 }
       
   147 
       
   148 /*! Returns true if this is not equal to \a other; false otherwise. */
       
   149 bool QVersitProperty::operator!=(const QVersitProperty& other) const
       
   150 {
       
   151     return !(*this == other);
       
   152 }
       
   153 
       
   154 /*! Returns the hash value for \a key. */
       
   155 uint qHash(const QVersitProperty &key)
       
   156 {
       
   157     uint hash = QT_PREPEND_NAMESPACE(qHash)(key.name()) + QT_PREPEND_NAMESPACE(qHash)(key.value());
       
   158     foreach (const QString& group, key.groups()) {
       
   159         hash += QT_PREPEND_NAMESPACE(qHash)(group);
       
   160     }
       
   161     QHash<QString,QString>::const_iterator it = key.parameters().constBegin();
       
   162     QHash<QString,QString>::const_iterator end = key.parameters().constEnd();
       
   163     while (it != end) {
       
   164         hash += QT_PREPEND_NAMESPACE(qHash)(it.key()) + QT_PREPEND_NAMESPACE(qHash)(it.value());
       
   165         ++it;
       
   166     }
       
   167     return hash;
       
   168 }
       
   169 
       
   170 #ifndef QT_NO_DEBUG_STREAM
       
   171 QDebug operator<<(QDebug dbg, const QVersitProperty& property)
       
   172 {
       
   173     QStringList groups = property.groups();
       
   174     QString name = property.name();
       
   175     QMultiHash<QString,QString> parameters = property.parameters();
       
   176     dbg.nospace() << "QVersitProperty(";
       
   177     foreach (const QString& group, groups) {
       
   178         dbg.nospace() << group << '.';
       
   179     }
       
   180     dbg.nospace() << name;
       
   181     QHash<QString,QString>::const_iterator it;
       
   182     for (it = parameters.constBegin(); it != parameters.constEnd(); ++it) {
       
   183         dbg.nospace() << ';' << it.key() << '=' << it.value();
       
   184     }
       
   185     dbg.nospace() << ':' << property.variantValue();
       
   186     dbg.nospace() << ')';
       
   187     return dbg.maybeSpace();
       
   188 }
       
   189 #endif
       
   190 
       
   191 /*!
       
   192  * Sets the groups in the property to the given list of \a groups.
       
   193  */
       
   194 void QVersitProperty::setGroups(const QStringList& groups)
       
   195 {
       
   196     d->mGroups.clear();
       
   197     foreach (const QString& group, groups) {
       
   198         d->mGroups.append(group);
       
   199     }
       
   200 }
       
   201 
       
   202 /*!
       
   203  * Gets the groups of the property.
       
   204  */
       
   205 QStringList QVersitProperty::groups() const
       
   206 {
       
   207     return d->mGroups;
       
   208 }
       
   209 
       
   210 /*!
       
   211  * Sets the \a name of the property.
       
   212  * The \a name is converted to upper-case.
       
   213  */
       
   214 void QVersitProperty::setName(const QString& name)
       
   215 {
       
   216     d->mName = name.toUpper();
       
   217 }
       
   218 
       
   219 /*!
       
   220  * Gets the name of the property in upper-case.
       
   221  */
       
   222 QString QVersitProperty::name() const
       
   223 {
       
   224     return d->mName;
       
   225 }
       
   226 
       
   227 /*!
       
   228  * Replaces all the parameters with \a parameters.
       
   229  * The parameters are converted to upper-case.
       
   230  */
       
   231 void QVersitProperty::setParameters(const QMultiHash<QString,QString>& parameters)
       
   232 {
       
   233     d->mParameters.clear();
       
   234     // Traverse parameters in the reverse order, because they are added to
       
   235     // d->mParameters using insert in QVersitProperty::addParameter
       
   236     QList<QString> keys = parameters.uniqueKeys();
       
   237     for (int i=keys.count()-1; i >= 0; i--) {
       
   238         QString key = keys.at(i);
       
   239         QList<QString> values = parameters.values(key);
       
   240         for (int j=values.count()-1; j >= 0; j--) {
       
   241             // Convert all the parameter names and values to upper case
       
   242             insertParameter(key,values.at(j));
       
   243         }
       
   244     }
       
   245 }
       
   246 
       
   247 /*!
       
   248  * Adds a new parameter with \a name and \a value.
       
   249  * Both the name and the value are converted to upper-case.
       
   250  */
       
   251 void QVersitProperty::insertParameter(const QString& name, const QString& value)
       
   252 {
       
   253     d->mParameters.insert(name.toUpper(), value);
       
   254 }
       
   255 
       
   256 /*!
       
   257  * Removes a parameter with \a name and \a value.
       
   258  *
       
   259  * \sa removeParameters()
       
   260  */
       
   261 void QVersitProperty::removeParameter(const QString& name, const QString& value)
       
   262 {
       
   263     d->mParameters.remove(name.toUpper(), value);
       
   264 }
       
   265 
       
   266 /*!
       
   267  * Removes all parameters with the given \a name.
       
   268  *
       
   269  * \sa removeParameter()
       
   270  */
       
   271 void QVersitProperty::removeParameters(const QString& name)
       
   272 {
       
   273     d->mParameters.remove(name.toUpper());
       
   274 }
       
   275 
       
   276 /*!
       
   277  * Return a copy of the contained list of parameters.
       
   278  * Note that actual the parameters cannot be modified using the copy.
       
   279  */
       
   280 QMultiHash<QString,QString> QVersitProperty::parameters() const
       
   281 {
       
   282     return d->mParameters;
       
   283 }
       
   284 
       
   285 /*!
       
   286  * Sets the property value to \a value.
       
   287  */
       
   288 void QVersitProperty::setValue(const QVariant& value)
       
   289 {
       
   290     d->mValue = value;
       
   291 }
       
   292 
       
   293 /*!
       
   294  * Returns the value of the property.
       
   295  */
       
   296 QVariant QVersitProperty::variantValue() const
       
   297 {
       
   298     return d->mValue;
       
   299 }
       
   300 
       
   301 /*!
       
   302  * \fn T QVersitProperty::value() const
       
   303  * \overload
       
   304  * Returns the value of the property as a \tt T.
       
   305  */
       
   306 
       
   307 /*!
       
   308  * Returns the value of the property as a string if possible, otherwise return an empty string.
       
   309  * If the property is stored as a QByteArray, it is decoded using the charset specified in the
       
   310  * property's parameters.
       
   311  * \sa QVariant::toString()
       
   312  */
       
   313 QString QVersitProperty::value() const
       
   314 {
       
   315     if (d->mValue.type() == QVariant::ByteArray) {
       
   316         if (d->mParameters.contains(QLatin1String("CHARSET"))) {
       
   317             QTextCodec* codec = QTextCodec::codecForName(
       
   318                     d->mParameters.value(QLatin1String("CHARSET")).toAscii());
       
   319             if (codec != NULL) {
       
   320                 return codec->toUnicode(d->mValue.toByteArray());
       
   321             }
       
   322         }
       
   323         return QString();
       
   324     } else {
       
   325         return d->mValue.toString();
       
   326     }
       
   327 }
       
   328 
       
   329 /*!
       
   330  * Sets the type of value held in the property to \a type.
       
   331  */
       
   332 void QVersitProperty::setValueType(QVersitProperty::ValueType type)
       
   333 {
       
   334     d->mValueType = type;
       
   335 }
       
   336 
       
   337 /*!
       
   338  * Returns the type of value held in the property.
       
   339  */
       
   340 QVersitProperty::ValueType QVersitProperty::valueType() const
       
   341 {
       
   342     return d->mValueType;
       
   343 }
       
   344 
       
   345 /*!
       
   346  * Returns true if the property is empty.
       
   347  */
       
   348 bool QVersitProperty::isEmpty() const
       
   349 {
       
   350     return d->mGroups.isEmpty()
       
   351             && d->mName.isEmpty()
       
   352             && d->mParameters.isEmpty()
       
   353             && !d->mValue.isValid();
       
   354 }
       
   355 
       
   356 /*!
       
   357  * Clears the contents of this property.
       
   358  */
       
   359 void QVersitProperty::clear()
       
   360 {
       
   361     d->mGroups.clear();
       
   362     d->mName.clear();
       
   363     d->mValue.clear();
       
   364     d->mParameters.clear();
       
   365 }
       
   366 
       
   367 QTM_END_NAMESPACE