~chris.gagnon/+junk/qtpim-coverage

« back to all changes in this revision

Viewing changes to src/organizer/qorganizercollectionid.cpp

  • Committer: chris.gagnon
  • Date: 2013-12-10 23:09:37 UTC
  • Revision ID: chris.gagnon@canonical.com-20131210230937-2akf1ft1edcttk87
first post

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtOrganizer module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include <qorganizercollectionid.h>
 
43
#include <qorganizercollectionengineid.h>
 
44
#include <private/qorganizermanager_p.h>
 
45
 
 
46
#include <QtCore/qstringlist.h>
 
47
 
 
48
#ifndef QT_NO_DEBUG_STREAM
 
49
#include <QtCore/qdebug.h>
 
50
#endif // QT_NO_DEBUG_STREAM
 
51
 
 
52
#if !defined(Q_CC_MWERKS)
 
53
QT_BEGIN_NAMESPACE
 
54
template<> QTORGANIZER_PREPEND_NAMESPACE(QOrganizerCollectionEngineId) *QSharedDataPointer<QTORGANIZER_PREPEND_NAMESPACE(QOrganizerCollectionEngineId)>::clone()
 
55
{
 
56
    return d ? d->clone() : 0;
 
57
}
 
58
QT_END_NAMESPACE
 
59
#endif // Q_CC_MWERKS
 
60
 
 
61
QT_BEGIN_NAMESPACE_ORGANIZER
 
62
 
 
63
/*!
 
64
    \class QOrganizerCollectionId
 
65
    \brief The QOrganizerCollectionId class provides information that uniquely identifies a collection
 
66
           in a particular manager.
 
67
    \inmodule QtOrganizer
 
68
    \ingroup organizer-main
 
69
 
 
70
    It consists of a manager URI which identifies the manager which manages the collection, and the
 
71
    ID of the collection in that manager.
 
72
 */
 
73
 
 
74
/*!
 
75
    Constructs a new, null collection ID.
 
76
 */
 
77
QOrganizerCollectionId::QOrganizerCollectionId()
 
78
    : d(0)
 
79
{
 
80
}
 
81
 
 
82
/*!
 
83
    Cleans up the memory in use by the collection ID.
 
84
 */
 
85
QOrganizerCollectionId::~QOrganizerCollectionId()
 
86
{
 
87
}
 
88
 
 
89
/*!
 
90
    Constructs a manager-unique ID which wraps the given engine-unique \a engineId.
 
91
 
 
92
    This ID takes ownership of the \a engineId and will delete it when this ID is destructed. Engine
 
93
    implementors must not delete the \a engineId, otherwise undefined behaviour will occur.
 
94
 */
 
95
QOrganizerCollectionId::QOrganizerCollectionId(QOrganizerCollectionEngineId *engineId)
 
96
    : d(engineId)
 
97
{
 
98
}
 
99
 
 
100
/*!
 
101
    Constructs a new collection ID as a copy of \a other.
 
102
 */
 
103
QOrganizerCollectionId::QOrganizerCollectionId(const QOrganizerCollectionId &other)
 
104
    : d(other.d)
 
105
{
 
106
}
 
107
 
 
108
/*!
 
109
    Assigns the collection ID to be equal to \a other.
 
110
 */
 
111
QOrganizerCollectionId &QOrganizerCollectionId::operator=(const QOrganizerCollectionId &other)
 
112
{
 
113
    d = other.d;
 
114
    return *this;
 
115
}
 
116
 
 
117
/*!
 
118
    Returns true if it has the same manager URI and ID as \a other.
 
119
*/
 
120
bool QOrganizerCollectionId::operator==(const QOrganizerCollectionId &other) const
 
121
{
 
122
    // if both ids are null then they are equal.
 
123
    if (d == 0 && other.d == 0)
 
124
        return true;
 
125
 
 
126
    if (d && other.d) {
 
127
        // ensure they're of the same type (and therefore comparable)
 
128
        if (d->managerUri() == other.d->managerUri())
 
129
            return d->isEqualTo(other.d);
 
130
    }
 
131
    return false;
 
132
}
 
133
 
 
134
/*!
 
135
    Returns true if either the manager URI or ID of it is different to that of \a other.
 
136
 */
 
137
bool QOrganizerCollectionId::operator!=(const QOrganizerCollectionId &other) const
 
138
{
 
139
    return !(*this == other);
 
140
}
 
141
 
 
142
/*!
 
143
    Returns true if this ID is less than the \a other.
 
144
 
 
145
    This ID will be considered less than the \a other if the manager URI of this ID is alphabetically
 
146
    less than the manager URI of the \a other. If both IDs have the same manager URI, this ID will
 
147
    be considered less than the \a other if the engine ID is less than the engine ID of the \a other.
 
148
 
 
149
    The invalid, empty ID consists of an empty manager URI and a null engine ID, and hence will be
 
150
    less than any non-invalid ID.
 
151
 
 
152
    This operator is provided primarily to allow use of a QOrganizerCollectionId as a key in a QMap.
 
153
 */
 
154
bool QOrganizerCollectionId::operator<(const QOrganizerCollectionId &other) const
 
155
{
 
156
    // a null id is always less than a non-null id.
 
157
    if (d == 0 && other.d != 0)
 
158
        return true;
 
159
 
 
160
    if (d && other.d) {
 
161
        // ensure they're of the same type (and therefore comparable)
 
162
        if (d->managerUri() == other.d->managerUri())
 
163
            return d->isLessThan(other.d);
 
164
 
 
165
        // not the same type?  just compare the manager uri.
 
166
        return d->managerUri() < other.d->managerUri();
 
167
    }
 
168
 
 
169
    return false;
 
170
}
 
171
 
 
172
/*!
 
173
    Returns true if the engine ID part of this ID is null (default constructed); otherwise, returns false.
 
174
 */
 
175
bool QOrganizerCollectionId::isNull() const
 
176
{
 
177
    return (d == 0);
 
178
}
 
179
 
 
180
/*!
 
181
    \relates QOrganizerCollectionId
 
182
    Returns the hash value for \a key.
 
183
 */
 
184
uint qHash(const QOrganizerCollectionId &key)
 
185
{
 
186
    if (key.d)
 
187
        return key.d->hash();
 
188
    return 0;
 
189
}
 
190
 
 
191
#ifndef QT_NO_DEBUG_STREAM
 
192
/*!
 
193
    \relates QOrganizerCollectionId
 
194
    Outputs \a id to the debug stream \a dbg.
 
195
 */
 
196
QDebug operator<<(QDebug dbg, const QOrganizerCollectionId &id)
 
197
{
 
198
    dbg.nospace() << "QOrganizerCollectionId(";
 
199
    if (id.isNull())
 
200
        dbg.nospace() << "(null))";
 
201
    else
 
202
        id.d->debugStreamOut(dbg)  << ")";
 
203
    return dbg.maybeSpace();
 
204
}
 
205
#endif // QT_NO_DEBUG_STREAM
 
206
 
 
207
#ifndef QT_NO_DATASTREAM
 
208
/*!
 
209
    \relates QOrganizerCollectionId
 
210
    Streams \a collectionId to the data stream \a out.
 
211
 */
 
212
QDataStream &operator<<(QDataStream &out, const QOrganizerCollectionId &collectionId)
 
213
{
 
214
    out << (collectionId.toString());
 
215
    return out;
 
216
}
 
217
 
 
218
/*!
 
219
    \relates QOrganizerCollectionId
 
220
    Streams \a collectionId in from the data stream \a in.
 
221
 */
 
222
QDataStream &operator>>(QDataStream &in, QOrganizerCollectionId &collectionId)
 
223
{
 
224
    QString idString;
 
225
    in >> idString;
 
226
    collectionId = QOrganizerCollectionId::fromString(idString);
 
227
    return in;
 
228
}
 
229
#endif // QT_NO_DATASTREAM
 
230
 
 
231
/*!
 
232
    Returns the URI of the manager which contains the collection identified by this ID.
 
233
 */
 
234
QString QOrganizerCollectionId::managerUri() const
 
235
{
 
236
    return d ? d->managerUri() : QString::null;
 
237
}
 
238
 
 
239
/*!
 
240
    \internal
 
241
 
 
242
    Builds a string from the given \a managerName, \a params and \a engineId.
 
243
 */
 
244
inline QString buildIdString(const QString &managerName, const QMap<QString, QString> &params, const QString &engineId)
 
245
{
 
246
    // the constructed id string will be of the form: "qtorganizer:managerName:param1=value1&param2=value2:
 
247
    QString ret(QStringLiteral("qtorganizer:%1:%2:%3"));
 
248
 
 
249
    // we have to escape each param
 
250
    QStringList escapedParams;
 
251
    QStringList keys = params.keys();
 
252
    for (int i = 0; i < keys.size(); ++i) {
 
253
        QString key = keys.at(i);
 
254
        QString arg = params.value(key);
 
255
        arg = arg.replace(QLatin1Char('&'), QStringLiteral("&amp;"));
 
256
        arg = arg.replace(QLatin1Char('='), QStringLiteral("&equ;"));
 
257
        arg = arg.replace(QLatin1Char(':'), QStringLiteral("&#58;"));
 
258
        key = key.replace(QLatin1Char('&'), QStringLiteral("&amp;"));
 
259
        key = key.replace(QLatin1Char('='), QStringLiteral("&equ;"));
 
260
        key = key.replace(QLatin1Char(':'), QStringLiteral("&#58;"));
 
261
        key = key + QLatin1Char('=') + arg;
 
262
        escapedParams.append(key);
 
263
    }
 
264
 
 
265
    // and we escape the engine id string.
 
266
    QString escapedEngineId = engineId;
 
267
    escapedEngineId.replace(QLatin1Char('&'), QStringLiteral("&amp;"));
 
268
    escapedEngineId.replace(QLatin1Char(':'), QStringLiteral("&#58;"));
 
269
 
 
270
    return ret.arg(managerName, escapedParams.join(QStringLiteral("&")), escapedEngineId);
 
271
}
 
272
 
 
273
/*!
 
274
    Serializes the ID to a string. The format of the string will be:
 
275
    "qtorganizer:managerName:constructionParams:serializedEngineLocalItemId".
 
276
 */
 
277
QString QOrganizerCollectionId::toString() const
 
278
{
 
279
    QString mgrName;
 
280
    QMap<QString, QString> params;
 
281
    QString engineId;
 
282
 
 
283
    if (d) {
 
284
        QOrganizerManager::parseUri(d->managerUri(), &mgrName, &params);
 
285
        engineId = d->toString();
 
286
    }
 
287
 
 
288
    // having extracted the params the name, we now need to build a new string.
 
289
    return buildIdString(mgrName, params, engineId);
 
290
}
 
291
 
 
292
/*!
 
293
    \internal
 
294
 
 
295
    Parses the individual components of the given \a idString and fills the \a managerName, \a params
 
296
    and \a engineIdString.
 
297
 
 
298
    Returns true if the parts could be parsed successfully, false otherwise.
 
299
 */
 
300
inline bool parseIdString(const QString &idString, QString *managerName, QMap<QString, QString> *params, QString *engineIdString)
 
301
{
 
302
    QStringList colonSplit = idString.split(QLatin1Char(':'));
 
303
 
 
304
    QString prefix = colonSplit.value(0);
 
305
    if (prefix != QStringLiteral("qtorganizer") || colonSplit.size() != 4)
 
306
        return false; // invalid serialized string.  we cannot continue.
 
307
 
 
308
    QString mgrName = colonSplit.value(1);
 
309
    QString paramString = colonSplit.value(2);
 
310
    QString engIdString = colonSplit.value(3);
 
311
 
 
312
    // Now we have to decode each parameter
 
313
    QMap<QString, QString> outParams;
 
314
    if (!paramString.isEmpty()) {
 
315
        QStringList params = paramString.split(QRegExp(QStringLiteral("&(?!(amp;|equ;))")), QString::KeepEmptyParts);
 
316
        // If we have an empty string for paramstring, we get one entry in params,
 
317
        // so skip that case.
 
318
        for (int i = 0; i < params.count(); ++i) {
 
319
            /* This should be something like "foo&amp;bar&equ;=grob&amp;" */
 
320
            QStringList paramChunk = params.value(i).split(QStringLiteral("="), QString::KeepEmptyParts);
 
321
 
 
322
            if (paramChunk.count() != 2)
 
323
                return false;
 
324
 
 
325
            QString arg = paramChunk.value(0);
 
326
            QString param = paramChunk.value(1);
 
327
 
 
328
            arg.replace(QStringLiteral("&#58;"), QStringLiteral(":"));
 
329
            arg.replace(QStringLiteral("&equ;"), QStringLiteral("="));
 
330
            arg.replace(QStringLiteral("&amp;"), QStringLiteral("&"));
 
331
            param.replace(QStringLiteral("&#58;"), QStringLiteral(":"));
 
332
            param.replace(QStringLiteral("&equ;"), QStringLiteral("="));
 
333
            param.replace(QStringLiteral("&amp;"), QStringLiteral("&"));
 
334
            if (arg.isEmpty())
 
335
                return false;
 
336
            outParams.insert(arg, param);
 
337
        }
 
338
    }
 
339
 
 
340
    // and unescape the engine id string.
 
341
    engIdString.replace(QStringLiteral("&#58;"), QStringLiteral(":"));
 
342
    engIdString.replace(QStringLiteral("&amp;"), QStringLiteral("&"));
 
343
 
 
344
    // now fill the return values.
 
345
    if (managerName)
 
346
        *managerName = mgrName;
 
347
    if (params)
 
348
        *params = outParams;
 
349
    if (engineIdString)
 
350
        *engineIdString = engIdString;
 
351
 
 
352
    // and return.
 
353
    return true;
 
354
}
 
355
 
 
356
/*!
 
357
    Deserializes the given \a idString.  Returns a default-constructed (null) collection ID if the
 
358
    given \a idString is not a valid, serialized collection ID, or if the manager engine from which
 
359
    the ID refers to could not be found.
 
360
 */
 
361
QOrganizerCollectionId QOrganizerCollectionId::fromString(const QString &idString)
 
362
{
 
363
    QString managerName;
 
364
    QMap<QString, QString> params;
 
365
    QString engineIdString;
 
366
 
 
367
    if (!parseIdString(idString, &managerName, &params, &engineIdString))
 
368
        return QOrganizerCollectionId(); // invalid idString given.
 
369
 
 
370
    QOrganizerCollectionEngineId *engineId = QOrganizerManagerData::createEngineCollectionId(managerName, params, engineIdString);
 
371
    return QOrganizerCollectionId(engineId);
 
372
}
 
373
 
 
374
QT_END_NAMESPACE_ORGANIZER