| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. |
| 4 | ** Contact: http://www.qt.io/licensing/ |
| 5 | ** |
| 6 | ** This file is part of the QtOrganizer module of the Qt Toolkit. |
| 7 | ** |
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
| 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 The Qt Company. For licensing terms |
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
| 15 | ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free |
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
| 22 | ** following information to ensure the GNU Lesser General Public License |
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 25 | ** |
| 26 | ** As a special exception, The Qt Company gives you certain additional |
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception |
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 29 | ** |
| 30 | ** $QT_END_LICENSE$ |
| 31 | ** |
| 32 | ****************************************************************************/ |
| 33 | |
| 34 | #include "qorganizeritem.h" |
| 35 | #include "qorganizeritem_p.h" |
| 36 | |
| 37 | #ifndef QT_NO_DATASTREAM |
| 38 | #include <QtCore/qdatastream.h> |
| 39 | #endif |
| 40 | #ifndef QT_NO_DEBUG_STREAM |
| 41 | #include <QtCore/qdebug.h> |
| 42 | #endif |
| 43 | |
| 44 | #include "qorganizeritemdetail_p.h" |
| 45 | #include "qorganizeritemdetails.h" |
| 46 | |
| 47 | QT_BEGIN_NAMESPACE_ORGANIZER |
| 48 | |
| 49 | /*! |
| 50 | \macro Q_DECLARE_CUSTOM_ORGANIZER_ITEM |
| 51 | \relates QOrganizerItem |
| 52 | |
| 53 | Macro for simplifying declaring convenience leaf classes for QOrganizerItem. |
| 54 | |
| 55 | The first argument is the name of the class, and the second argument is the |
| 56 | item type. |
| 57 | */ |
| 58 | |
| 59 | /*! |
| 60 | \class QOrganizerItem |
| 61 | \brief The QOrganizerItem class is the base class of an event, todo, note, or journal entry. |
| 62 | \inmodule QtOrganizer |
| 63 | \ingroup organizer-main |
| 64 | |
| 65 | A QOrganizerItem object has an id and a collection of details (like a start date and location), as |
| 66 | well as a collection id which identifies which QOrganizerCollection the item is part of in a manager. |
| 67 | Each detail (which can have multiple fields) is stored in an appropriate subclass of QOrganizerItemDetail, |
| 68 | and the QOrganizerItem allows retrieving these details in various ways. QOrganizerItemExtendedDetail is |
| 69 | supposed to be used to store user specific details that are not pre-defined in the detal leaf classes. |
| 70 | |
| 71 | Most clients will want to use the convenient subclasses of QOrganizerItem (i.e., QOrganizerEvent |
| 72 | (and QOrganizerEventOccurence), QOrganizerTodo (and QOrganizerTodoOccurence), QOrganizerJournal and |
| 73 | QOrganizerNote) instead of manipulating instances of QOrganizerItem directly. |
| 74 | |
| 75 | A QOrganizerItem instance represents the in-memory version of an organizer item. |
| 76 | It is possible for the contents of a QOrganizerItem to change independently of the contents |
| 77 | that are stored persistently in a QOrganizerManager. A QOrganizerItem has an id associated |
| 78 | with it when it is first retrieved from a QOrganizerManager, or after it has been first saved, |
| 79 | and this allows clients to track changes using the signals in QOrganizerManager. When saved |
| 80 | in a manager, every item is placed into a QOrganizerCollection in that manager, according |
| 81 | to the collection id set in the item prior to save (or the default collection if no |
| 82 | collection id was set in the item). |
| 83 | |
| 84 | Different QOrganizerManagers may require an item to have certain details saved in it before |
| 85 | it can be stored in that manager. By default, every item must have a QOrganizerItemType |
| 86 | detail which identifies the type of the item. Different subclasses of QOrganizerItem |
| 87 | (i.e., QOrganizerEvent (and QOrganizerEventOccurence), QOrganizerTodo (and QOrganizerTodoOccurence), |
| 88 | QOrganizerJournal and QOrganizerNote) may have other mandatory details, depending on the manager. |
| 89 | |
| 90 | \sa QOrganizerManager, QOrganizerItemDetail |
| 91 | */ |
| 92 | |
| 93 | /*! |
| 94 | \fn QOrganizerItem::operator!=(const QOrganizerItem &other) const |
| 95 | |
| 96 | Returns true if this organizer item's id or details are different to those of the \a other organizer item. |
| 97 | */ |
| 98 | |
| 99 | /*! |
| 100 | Construct an empty organizer item. |
| 101 | |
| 102 | The organizer item will have an empty item ID, and an empty collection ID. It's of type \l QOrganizerItemType::TypeUndefined. |
| 103 | */ |
| 104 | QOrganizerItem::QOrganizerItem() |
| 105 | : d(new QOrganizerItemData) |
| 106 | { |
| 107 | QOrganizerItemType organizeritemType; |
| 108 | organizeritemType.setType(QOrganizerItemType::TypeUndefined); |
| 109 | d->m_details.append(t: organizeritemType); |
| 110 | } |
| 111 | |
| 112 | /*! |
| 113 | Constructs an item that is a copy of \a other. |
| 114 | */ |
| 115 | QOrganizerItem::QOrganizerItem(const QOrganizerItem &other) |
| 116 | : d(other.d) |
| 117 | { |
| 118 | } |
| 119 | |
| 120 | /*! |
| 121 | \internal |
| 122 | |
| 123 | Constructs a new, empty item of the given type \a type. |
| 124 | */ |
| 125 | QOrganizerItem::QOrganizerItem(QOrganizerItemType::ItemType type) |
| 126 | : d(new QOrganizerItemData) |
| 127 | { |
| 128 | QOrganizerItemType organizeritemType; |
| 129 | organizeritemType.setType(type); |
| 130 | d->m_details.append(t: organizeritemType); |
| 131 | } |
| 132 | |
| 133 | /*! |
| 134 | \internal |
| 135 | |
| 136 | Constructs an item that is a copy of \a other if \a other is of the expected type |
| 137 | identified by \a expectedType, else constructs a new, empty item of the |
| 138 | type identified by the \a expectedType. |
| 139 | |
| 140 | The \a expectedType pointer must be valid for the lifetime of the program. |
| 141 | */ |
| 142 | QOrganizerItem::QOrganizerItem(const QOrganizerItem &other, QOrganizerItemType::ItemType expectedType) |
| 143 | { |
| 144 | if (other.type() == expectedType) { |
| 145 | d = other.d; |
| 146 | } else { |
| 147 | d = new QOrganizerItemData; |
| 148 | setType(expectedType); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | /*! |
| 153 | \internal |
| 154 | |
| 155 | Assigns this item to \a other if the type of \a other is that identified |
| 156 | by the given \a expectedType, else assigns this item to be a new, empty |
| 157 | item of the type identified by the given \a expectedType |
| 158 | */ |
| 159 | QOrganizerItem &QOrganizerItem::assign(const QOrganizerItem &other, QOrganizerItemType::ItemType expectedType) |
| 160 | { |
| 161 | if (this != &other) { |
| 162 | if (other.type() == expectedType) { |
| 163 | d = other.d; |
| 164 | } else { |
| 165 | d = new QOrganizerItemData; |
| 166 | setType(expectedType); |
| 167 | } |
| 168 | } |
| 169 | return *this; |
| 170 | } |
| 171 | |
| 172 | |
| 173 | /*! |
| 174 | Returns true if this QOrganizerItem is empty, false if not. |
| 175 | |
| 176 | Note that the type detail of the organizer item is irrelevant. |
| 177 | */ |
| 178 | bool QOrganizerItem::isEmpty() const |
| 179 | { |
| 180 | return (d->m_details.count() == 1); |
| 181 | } |
| 182 | |
| 183 | /*! |
| 184 | Removes all details of the organizer item, and resets the type to be \l QOrganizerItemType::TypeUndefined. |
| 185 | */ |
| 186 | void QOrganizerItem::clearDetails() |
| 187 | { |
| 188 | d->m_details.clear(); |
| 189 | |
| 190 | QOrganizerItemType organizeritemType; |
| 191 | organizeritemType.setType(QOrganizerItemType::TypeUndefined); |
| 192 | d->m_details.append(t: organizeritemType); |
| 193 | } |
| 194 | |
| 195 | /*! |
| 196 | Replace the contents of this organizer item with the \a other. |
| 197 | */ |
| 198 | QOrganizerItem &QOrganizerItem::operator=(const QOrganizerItem &other) |
| 199 | { |
| 200 | d = other.d; |
| 201 | return *this; |
| 202 | } |
| 203 | |
| 204 | /*! |
| 205 | Frees the memory used by this item. |
| 206 | */ |
| 207 | QOrganizerItem::~QOrganizerItem() |
| 208 | { |
| 209 | } |
| 210 | |
| 211 | /*! |
| 212 | Returns the QOrganizerItemId that identifies this organizer item. |
| 213 | |
| 214 | This may have been set when the organizer item was retrieved from |
| 215 | a particular manager, or when the organizer item was first saved |
| 216 | in a manager. The QOrganizerItemId is only valid within a specific |
| 217 | manager. See \l QOrganizerManager::saveItem() for more |
| 218 | information. |
| 219 | */ |
| 220 | QOrganizerItemId QOrganizerItem::id() const |
| 221 | { |
| 222 | return d->m_id; |
| 223 | } |
| 224 | |
| 225 | /*! |
| 226 | Returns the id of the collection which this item is part of, in the manager |
| 227 | in which the item has been saved, if the item has previously been saved in |
| 228 | a manager. If the item has not previously been saved in a manager, this function |
| 229 | will return the id of the collection into which the client wishes the item to be |
| 230 | saved when \l QOrganizerManager::saveItem() is called, which is set by calling |
| 231 | \l setId(); otherwise, returns a null id. |
| 232 | |
| 233 | An item always belongs to exactly one collection in a particular manager after it |
| 234 | has been saved in the manager. If the item has previously been saved in the manager, |
| 235 | in a particular collection, and the client sets the collection id of the item to |
| 236 | the id of a different collection within that manager and then resaves the item, |
| 237 | the item will be moved from its original collection into the specified collection |
| 238 | if the move operation is supported by the manager; otherwise, the |
| 239 | \l QOrganizerManager::saveItem() operation will fail and calling |
| 240 | \l QOrganizerManager::error() will return \c QOrganizerManager::NotSupportedError. |
| 241 | */ |
| 242 | QOrganizerCollectionId QOrganizerItem::collectionId() const |
| 243 | { |
| 244 | return d->m_collectionId; |
| 245 | } |
| 246 | |
| 247 | /*! |
| 248 | Sets the id of the collection into which the client wishes the item to be saved |
| 249 | to the given \a collectionId. |
| 250 | |
| 251 | If the given \a collectionId is the null collection id, the client is specifying |
| 252 | that the item should be saved into the collection in which the item is already |
| 253 | saved (if the item has previously been saved in the manager, without having been |
| 254 | removed since), or into the default collection of the manager (if the item has |
| 255 | not previously been saved in the manager, or has been removed since the last time |
| 256 | it was saved). |
| 257 | |
| 258 | If the item has previously been saved in a particular manager, and the given |
| 259 | \a collectionId is the id of a different collection than the one which the |
| 260 | item is currently a part of in that manager, saving the item with |
| 261 | \l QOrganizerManager::saveItem() will move the item from its original |
| 262 | collection to the collection whose id is \a collectionId, if \a collectionId |
| 263 | identifies a valid collection and the operation is supported by the manager. |
| 264 | */ |
| 265 | void QOrganizerItem::setCollectionId(const QOrganizerCollectionId &collectionId) |
| 266 | { |
| 267 | d->m_collectionId = collectionId; |
| 268 | } |
| 269 | |
| 270 | /*! |
| 271 | Sets the id of this organizer item to \a id. |
| 272 | |
| 273 | Note that this only affects this object, not any corresponding structures stored |
| 274 | by a QOrganizerManager. |
| 275 | |
| 276 | If you change the id of a organizer item and save the organizer item |
| 277 | in a manager, the previously existing organizer item will still |
| 278 | exist. You can do this to create copies (possibly modified) |
| 279 | of an existing organizer item, or to save a organizer item in a different manager. |
| 280 | |
| 281 | \sa QOrganizerManager::saveItem() |
| 282 | */ |
| 283 | void QOrganizerItem::setId(const QOrganizerItemId &id) |
| 284 | { |
| 285 | d->m_id = id; |
| 286 | // TODO - reset collection id? |
| 287 | } |
| 288 | |
| 289 | /*! |
| 290 | Returns the first detail stored in the organizer item with the given \a detailType. If the |
| 291 | given \a detailType is TypeUndefined, it returns the first detail found. |
| 292 | */ |
| 293 | QOrganizerItemDetail QOrganizerItem::detail(QOrganizerItemDetail::DetailType detailType) const |
| 294 | { |
| 295 | if (detailType == QOrganizerItemDetail::TypeUndefined) |
| 296 | return d->m_details.first(); |
| 297 | |
| 298 | for (int i = 0; i < d->m_details.size(); i++) { |
| 299 | const QOrganizerItemDetail &existing = d->m_details.at(i); |
| 300 | if (existing.d->m_detailType == detailType) |
| 301 | return existing; |
| 302 | } |
| 303 | |
| 304 | return QOrganizerItemDetail(); |
| 305 | } |
| 306 | |
| 307 | /*! |
| 308 | Returns a list of details with the given \a detailType. If the given \a detailType is of TypeUndefined, |
| 309 | it returns all the details. |
| 310 | */ |
| 311 | QList<QOrganizerItemDetail> QOrganizerItem::details(QOrganizerItemDetail::DetailType detailType) const |
| 312 | { |
| 313 | if (detailType == QOrganizerItemDetail::TypeUndefined) |
| 314 | return d->m_details; |
| 315 | |
| 316 | QList<QOrganizerItemDetail> sublist; |
| 317 | for (int i = 0; i < d->m_details.size(); i++) { |
| 318 | const QOrganizerItemDetail &existing = d->m_details.at(i); |
| 319 | if (existing.d->m_detailType == detailType) |
| 320 | sublist.append(t: existing); |
| 321 | } |
| 322 | return sublist; |
| 323 | } |
| 324 | |
| 325 | /*! |
| 326 | Saves the given \a detail in the list of stored details, and sets the detail's id. |
| 327 | If another detail of the same type and id has been previously saved in |
| 328 | this organizer item, that detail is overwritten. Otherwise, a new id is generated |
| 329 | and set in the detail, and the detail is added to the organizer item. |
| 330 | |
| 331 | If \a detail is a QOrganizerItemType, the existing organizer item type will |
| 332 | be overwritten with \a detail. There is never more than one organizer item type |
| 333 | in a organizer item. |
| 334 | |
| 335 | Returns true if the detail was saved successfully, otherwise returns false. |
| 336 | |
| 337 | Note that the caller retains ownership of the detail. |
| 338 | */ |
| 339 | bool QOrganizerItem::saveDetail(QOrganizerItemDetail *detail) |
| 340 | { |
| 341 | if (!detail) |
| 342 | return false; |
| 343 | |
| 344 | // we only allow one instance of these details per item |
| 345 | if (detail->d.constData()->m_detailType == QOrganizerItemDetail::TypeItemType |
| 346 | || detail->d.constData()->m_detailType == QOrganizerItemDetail::TypeDescription |
| 347 | || detail->d.constData()->m_detailType == QOrganizerItemDetail::TypeDisplayLabel |
| 348 | || detail->d.constData()->m_detailType == QOrganizerItemDetail::TypeClassification |
| 349 | || detail->d.constData()->m_detailType == QOrganizerItemDetail::TypeVersion) { |
| 350 | for (int i = 0; i < d.constData()->m_details.size(); i++) { |
| 351 | if (detail->d.constData()->m_detailType == d.constData()->m_details.at(i).d.constData()->m_detailType) { |
| 352 | d->m_details.replace(i, t: *detail); |
| 353 | return true; |
| 354 | } |
| 355 | } |
| 356 | // doesn't already exist; append it. |
| 357 | d->m_details.append(t: *detail); |
| 358 | return true; |
| 359 | } |
| 360 | |
| 361 | // try to find the "old version" of this field |
| 362 | // ie, the one with the same type and id, but different value or attributes. |
| 363 | for (int i = 0; i < d.constData()->m_details.size(); i++) { |
| 364 | const QOrganizerItemDetail& curr = d.constData()->m_details.at(i); |
| 365 | if (detail->d.constData()->m_detailType == curr.d.constData()->m_detailType && detail->d.constData()->m_id == curr.d.constData()->m_id) { |
| 366 | // update the detail constraints of the supplied detail |
| 367 | // Found the old version. Replace it with this one. |
| 368 | d->m_details[i] = *detail; |
| 369 | return true; |
| 370 | } |
| 371 | } |
| 372 | // this is a new detail! add it to the organizer item. |
| 373 | d->m_details.append(t: *detail); |
| 374 | return true; |
| 375 | } |
| 376 | |
| 377 | /*! |
| 378 | Removes the \a detail from the organizer item. |
| 379 | |
| 380 | The detail in the organizer item which has the same key as that of the given \a detail |
| 381 | will be removed if it exists. Only the key is used for comparison - that is, the |
| 382 | information in the detail may be different. |
| 383 | |
| 384 | Returns true if the detail was removed successfully, false if an error occurred. |
| 385 | |
| 386 | Note that the caller retains ownership of the detail. |
| 387 | */ |
| 388 | bool QOrganizerItem::removeDetail(QOrganizerItemDetail *detail) |
| 389 | { |
| 390 | if (!detail) |
| 391 | return false; |
| 392 | |
| 393 | // find the detail stored in the organizer item which has the same key as the detail argument |
| 394 | int removeIndex = -1; |
| 395 | for (int i = 0; i < d.constData()->m_details.size(); i++) { |
| 396 | if (d.constData()->m_details.at(i).key() == detail->key()) { |
| 397 | removeIndex = i; |
| 398 | break; |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | // make sure the detail exists (in some form) in the organizer item. |
| 403 | if (removeIndex < 0) |
| 404 | return false; |
| 405 | |
| 406 | // Type -detail is specific case which cannot be deleted |
| 407 | if (QOrganizerItemDetail::TypeItemType == detail->d.constData()->m_detailType) |
| 408 | return false; |
| 409 | |
| 410 | if (!d.constData()->m_details.contains(t: *detail)) |
| 411 | return false; |
| 412 | |
| 413 | // then remove the detail. |
| 414 | d->m_details.removeAt(i: removeIndex); |
| 415 | return true; |
| 416 | } |
| 417 | |
| 418 | /*! |
| 419 | Returns true if this organizer item is equal to the \a other organizer item, false if either the |
| 420 | id, collection id or stored details are not the same. |
| 421 | */ |
| 422 | bool QOrganizerItem::operator==(const QOrganizerItem &other) const |
| 423 | { |
| 424 | if (d == other.d) |
| 425 | return true; |
| 426 | |
| 427 | if (other.d->m_id != d->m_id |
| 428 | || other.d->m_collectionId != d->m_collectionId |
| 429 | || d->m_details.size() != other.d->m_details.size()) { |
| 430 | return false; |
| 431 | } |
| 432 | |
| 433 | QList<QOrganizerItemDetail> searchList(d->m_details); |
| 434 | foreach (const QOrganizerItemDetail &detail, other.d->m_details) { |
| 435 | if (!searchList.removeOne(t: detail)) |
| 436 | return false; |
| 437 | } |
| 438 | |
| 439 | return true; |
| 440 | } |
| 441 | |
| 442 | /*! |
| 443 | \relates QOrganizerItem |
| 444 | |
| 445 | Returns the hash value for \a key. |
| 446 | */ |
| 447 | uint qHash(const QOrganizerItem &key) |
| 448 | { |
| 449 | uint hash = qHash(id: key.id()); |
| 450 | hash += qHash(id: key.collectionId()); |
| 451 | foreach (const QOrganizerItemDetail &detail, key.details()) |
| 452 | hash += qHash(key: detail); |
| 453 | return hash; |
| 454 | } |
| 455 | |
| 456 | #ifndef QT_NO_DEBUG_STREAM |
| 457 | /*! |
| 458 | \relates QOrganizerItem |
| 459 | Streams the \a item to the given debug stream \a dbg, and returns the stream. |
| 460 | */ |
| 461 | QDebug operator<<(QDebug dbg, const QOrganizerItem &item) |
| 462 | { |
| 463 | dbg.nospace() << "QOrganizerItem(" << item.id() << ") in collection(" << item.collectionId() << ")" ; |
| 464 | foreach (const QOrganizerItemDetail& detail, item.details()) |
| 465 | dbg.space() << '\n' << detail; |
| 466 | return dbg.maybeSpace(); |
| 467 | } |
| 468 | #endif // QT_NO_DEBUG_STREAM |
| 469 | |
| 470 | #ifndef QT_NO_DATASTREAM |
| 471 | /*! |
| 472 | \relates QOrganizerItem |
| 473 | Writes \a item to the stream \a out. |
| 474 | */ |
| 475 | QDataStream &operator<<(QDataStream &out, const QOrganizerItem &item) |
| 476 | { |
| 477 | quint8 formatVersion = 1; // Version of QDataStream format for QOrganizerItem |
| 478 | out << formatVersion |
| 479 | << item.id().toString() |
| 480 | << item.collectionId().toString() |
| 481 | << item.details(); |
| 482 | return out; |
| 483 | } |
| 484 | |
| 485 | /*! |
| 486 | \relates QOrganizerItem |
| 487 | Reads an item from stream \a in into \a item. |
| 488 | */ |
| 489 | QDataStream &operator>>(QDataStream &in, QOrganizerItem &item) |
| 490 | { |
| 491 | quint8 formatVersion; |
| 492 | in >> formatVersion; |
| 493 | if (formatVersion == 1) { |
| 494 | item = QOrganizerItem(); |
| 495 | QString itemIdString; |
| 496 | QString collectionIdString; |
| 497 | QList<QOrganizerItemDetail> details; |
| 498 | in >> itemIdString >> collectionIdString >> details; |
| 499 | item.setId(QOrganizerItemId::fromString(idString: itemIdString)); |
| 500 | item.setCollectionId(QOrganizerCollectionId::fromString(idString: collectionIdString)); |
| 501 | item.d->m_details = details; |
| 502 | } else { |
| 503 | in.setStatus(QDataStream::ReadCorruptData); |
| 504 | } |
| 505 | return in; |
| 506 | } |
| 507 | #endif // QT_NO_DATASTREAM |
| 508 | |
| 509 | /*! |
| 510 | Returns the type of the organizer item. |
| 511 | */ |
| 512 | QOrganizerItemType::ItemType QOrganizerItem::type() const |
| 513 | { |
| 514 | // type is always the first detail |
| 515 | QOrganizerItemType type = static_cast<QOrganizerItemType>(d->m_details.at(i: 0)); |
| 516 | return type.type(); |
| 517 | } |
| 518 | |
| 519 | /*! |
| 520 | Sets the type of the organizer item to the given \a type. |
| 521 | */ |
| 522 | void QOrganizerItem::setType(QOrganizerItemType::ItemType type) |
| 523 | { |
| 524 | if (d->m_details.isEmpty()) { |
| 525 | QOrganizerItemType organizeritemType; |
| 526 | organizeritemType.setType(type); |
| 527 | d->m_details.append(t: organizeritemType); |
| 528 | } else { |
| 529 | // type is always the first detail |
| 530 | d->m_details.first().setValue(field: QOrganizerItemType::FieldType, value: type); |
| 531 | } |
| 532 | } |
| 533 | |
| 534 | /*! |
| 535 | Returns the display label of the item. |
| 536 | */ |
| 537 | QString QOrganizerItem::displayLabel() const |
| 538 | { |
| 539 | QOrganizerItemDisplayLabel dl = detail(detailType: QOrganizerItemDetail::TypeDisplayLabel); |
| 540 | return dl.label(); |
| 541 | } |
| 542 | |
| 543 | /*! |
| 544 | Sets the display label of the item to \a label. |
| 545 | */ |
| 546 | void QOrganizerItem::setDisplayLabel(const QString &label) |
| 547 | { |
| 548 | QOrganizerItemDisplayLabel dl = detail(detailType: QOrganizerItemDetail::TypeDisplayLabel); |
| 549 | dl.setLabel(label); |
| 550 | saveDetail(detail: &dl); |
| 551 | } |
| 552 | |
| 553 | /*! |
| 554 | Returns the human-readable description of the item. |
| 555 | */ |
| 556 | QString QOrganizerItem::description() const |
| 557 | { |
| 558 | QOrganizerItemDescription descr = detail(detailType: QOrganizerItemDetail::TypeDescription); |
| 559 | return descr.description(); |
| 560 | } |
| 561 | |
| 562 | /*! |
| 563 | Sets the human-readable description of the item to \a description. |
| 564 | */ |
| 565 | void QOrganizerItem::setDescription(const QString &description) |
| 566 | { |
| 567 | QOrganizerItemDescription descr = detail(detailType: QOrganizerItemDetail::TypeDescription); |
| 568 | descr.setDescription(description); |
| 569 | saveDetail(detail: &descr); |
| 570 | } |
| 571 | |
| 572 | /*! |
| 573 | Returns the list of comments of this item. |
| 574 | */ |
| 575 | QStringList QOrganizerItem::() const |
| 576 | { |
| 577 | QStringList ; |
| 578 | for (int i = 0; i < d->m_details.size(); ++i) { |
| 579 | const QOrganizerItemDetail &detail = d->m_details.at(i); |
| 580 | if (detail.d->m_detailType == QOrganizerItemDetail::TypeComment) |
| 581 | commentList.append(t: detail.d->m_values.value(akey: QOrganizerItemComment::FieldComment).toString()); |
| 582 | } |
| 583 | return commentList; |
| 584 | } |
| 585 | |
| 586 | /*! |
| 587 | Removes all comments of this item. |
| 588 | */ |
| 589 | void QOrganizerItem::() |
| 590 | { |
| 591 | d->removeOnly(detailType: QOrganizerItemDetail::TypeComment); |
| 592 | } |
| 593 | |
| 594 | /*! |
| 595 | Sets the list of comments associated with the item to \a comments. |
| 596 | */ |
| 597 | void QOrganizerItem::(const QStringList &) |
| 598 | { |
| 599 | d->removeOnly(detailType: QOrganizerItemDetail::TypeComment); |
| 600 | foreach (const QString &, comments) |
| 601 | addComment(comment); |
| 602 | } |
| 603 | |
| 604 | /*! |
| 605 | Adds the \a comment to this item |
| 606 | */ |
| 607 | void QOrganizerItem::(const QString &) |
| 608 | { |
| 609 | QOrganizerItemComment detail; |
| 610 | detail.setComment(comment); |
| 611 | saveDetail(detail: &detail); |
| 612 | } |
| 613 | |
| 614 | /*! |
| 615 | Returns the list of tags for this item. |
| 616 | */ |
| 617 | QStringList QOrganizerItem::tags() const |
| 618 | { |
| 619 | QStringList tagList; |
| 620 | for (int i = 0; i < d->m_details.size(); ++i) { |
| 621 | const QOrganizerItemDetail &detail = d->m_details.at(i); |
| 622 | if (detail.d->m_detailType == QOrganizerItemDetail::TypeTag) |
| 623 | tagList.append(t: detail.d->m_values.value(akey: QOrganizerItemTag::FieldTag).toString()); |
| 624 | } |
| 625 | return tagList; |
| 626 | } |
| 627 | |
| 628 | /*! |
| 629 | Removes all tags associated with the item. |
| 630 | */ |
| 631 | void QOrganizerItem::clearTags() |
| 632 | { |
| 633 | d->removeOnly(detailType: QOrganizerItemDetail::TypeTag); |
| 634 | } |
| 635 | |
| 636 | /*! |
| 637 | Adds the \a tag to this item. |
| 638 | */ |
| 639 | void QOrganizerItem::addTag(const QString &tag) |
| 640 | { |
| 641 | QOrganizerItemTag tagDetail; |
| 642 | tagDetail.setTag(tag); |
| 643 | saveDetail(detail: &tagDetail); |
| 644 | } |
| 645 | |
| 646 | /*! |
| 647 | Sets the list of tags associated with the item to \a tags. |
| 648 | */ |
| 649 | void QOrganizerItem::setTags(const QStringList &tags) |
| 650 | { |
| 651 | d->removeOnly(detailType: QOrganizerItemDetail::TypeTag); |
| 652 | foreach (const QString &tag, tags) |
| 653 | addTag(tag); |
| 654 | } |
| 655 | |
| 656 | /*! |
| 657 | Returns the globally unique identifier which identifies this item, |
| 658 | which is used for synchronization purposes. |
| 659 | */ |
| 660 | QString QOrganizerItem::guid() const |
| 661 | { |
| 662 | QOrganizerItemGuid guid = detail(detailType: QOrganizerItemDetail::TypeGuid); |
| 663 | return guid.guid(); |
| 664 | } |
| 665 | |
| 666 | /*! |
| 667 | Sets the item's globally unique identifier to \a guid. |
| 668 | */ |
| 669 | void QOrganizerItem::setGuid(const QString &guid) |
| 670 | { |
| 671 | QOrganizerItemGuid guidDetail = detail(detailType: QOrganizerItemDetail::TypeGuid); |
| 672 | guidDetail.setGuid(guid); |
| 673 | saveDetail(detail: &guidDetail); |
| 674 | } |
| 675 | |
| 676 | /*! |
| 677 | Returns the data of the extended detail with the given \a name. |
| 678 | */ |
| 679 | QVariant QOrganizerItem::data(const QString &name) const |
| 680 | { |
| 681 | for (int i = 0; i < d->m_details.size(); ++i) { |
| 682 | const QOrganizerItemDetail &detail = d->m_details.at(i); |
| 683 | if (detail.d->m_detailType == QOrganizerItemDetail::TypeExtendedDetail |
| 684 | && detail.d->m_values.value(akey: QOrganizerItemExtendedDetail::FieldName).toString() == name) { |
| 685 | return detail.d->m_values.value(akey: QOrganizerItemExtendedDetail::FieldData); |
| 686 | } |
| 687 | } |
| 688 | return QVariant(); |
| 689 | } |
| 690 | |
| 691 | /*! |
| 692 | Sets the \a data of a extended detail with the given \a name. |
| 693 | */ |
| 694 | void QOrganizerItem::setData(const QString &name, const QVariant &data) |
| 695 | { |
| 696 | for (int i = 0; i < d->m_details.size(); ++i) { |
| 697 | const QOrganizerItemDetail &detail = d->m_details.at(i); |
| 698 | if (detail.d->m_detailType == QOrganizerItemDetail::TypeExtendedDetail |
| 699 | && detail.d->m_values.value(akey: QOrganizerItemExtendedDetail::FieldName).toString() == name) { |
| 700 | QOrganizerItemDetail newDetail = d->m_details.at(i); |
| 701 | newDetail.d->m_values.insert(akey: QOrganizerItemExtendedDetail::FieldData, avalue: data); |
| 702 | saveDetail(detail: &newDetail); |
| 703 | return; |
| 704 | } |
| 705 | } |
| 706 | |
| 707 | QOrganizerItemExtendedDetail newDetail; |
| 708 | newDetail.setName(name); |
| 709 | newDetail.setData(data); |
| 710 | saveDetail(detail: &newDetail); |
| 711 | } |
| 712 | |
| 713 | /*! |
| 714 | \internal |
| 715 | */ |
| 716 | void QOrganizerItemData::removeOnly(QOrganizerItemDetail::DetailType detailType) |
| 717 | { |
| 718 | QList<QOrganizerItemDetail>::iterator dit = m_details.begin(); |
| 719 | while (dit != m_details.end()) { |
| 720 | // XXX this doesn't check type or display label |
| 721 | if (dit->type() == detailType) |
| 722 | dit = m_details.erase(it: dit); |
| 723 | else |
| 724 | ++dit; |
| 725 | } |
| 726 | } |
| 727 | |
| 728 | /*! |
| 729 | \internal |
| 730 | */ |
| 731 | void QOrganizerItemData::removeOnly(const QSet<QOrganizerItemDetail::DetailType> &detailTypes) |
| 732 | { |
| 733 | QList<QOrganizerItemDetail>::iterator dit = m_details.begin(); |
| 734 | while (dit != m_details.end()) { |
| 735 | // XXX this doesn't check type or display label |
| 736 | if (detailTypes.contains(value: dit->type())) |
| 737 | dit = m_details.erase(it: dit); |
| 738 | else |
| 739 | ++dit; |
| 740 | } |
| 741 | } |
| 742 | |
| 743 | QT_END_NAMESPACE_ORGANIZER |
| 744 | |