• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.13.3 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • akonadi
item.cpp
1 /*
2  Copyright (c) 2006 Volker Krause <vkrause@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "item.h"
21 #include "item_p.h"
22 #include "itemserializer_p.h"
23 #include "protocol_p.h"
24 
25 #include <kurl.h>
26 #include <kdebug.h>
27 
28 #include <QtCore/QStringList>
29 #include <QtCore/QReadWriteLock>
30 
31 #include <algorithm>
32 #include <map>
33 #include <utility>
34 
35 using namespace Akonadi;
36 using namespace boost;
37 
38 namespace {
39 
40 struct nodelete {
41  template <typename T>
42  void operator()( T * ) {}
43 };
44 
45 struct ByTypeId {
46  typedef bool result_type;
47  bool operator()( const boost::shared_ptr<PayloadBase> & lhs, const boost::shared_ptr<PayloadBase> & rhs ) const {
48  return strcmp( lhs->typeName(), rhs->typeName() ) < 0 ;
49  }
50 };
51 
52 } // anon namespace
53 
54 typedef QHash< QString, std::map< boost::shared_ptr<PayloadBase>, std::pair<int,int>, ByTypeId > > LegacyMap;
55 Q_GLOBAL_STATIC( LegacyMap, typeInfoToMetaTypeIdMap )
56 Q_GLOBAL_STATIC_WITH_ARGS( QReadWriteLock, legacyMapLock, ( QReadWriteLock::Recursive ) )
57 
58 void Item::addToLegacyMappingImpl( const QString & mimeType, int spid, int mtid, std::auto_ptr<PayloadBase> p ) {
59  if ( !p.get() ) {
60  return;
61  }
62  const boost::shared_ptr<PayloadBase> sp( p );
63  const QWriteLocker locker( legacyMapLock() );
64  std::pair<int,int> & item = ( *typeInfoToMetaTypeIdMap() )[mimeType][sp];
65  item.first = spid;
66  item.second = mtid;
67 }
68 
69 namespace {
70  class MyReadLocker {
71  public:
72  explicit MyReadLocker( QReadWriteLock * rwl ) : rwl( rwl ), locked( false ) { if ( rwl ) rwl->lockForRead(); locked = true; }
73  ~MyReadLocker() { if ( rwl && locked ) rwl->unlock(); }
74 
75  template <typename T>
76  shared_ptr<T> makeUnlockingPointer( T * t ) {
77  if ( t ) {
78  // the bind() doesn't throw, so if shared_ptr
79  // construction line below, or anything else after it,
80  // throws, we're unlocked. Mark us as such:
81  locked = false;
82  const shared_ptr<T> result( t, bind( &QReadWriteLock::unlock, rwl ) );
83  // from now on, the shared_ptr is responsible for unlocking
84  return result;
85  } else {
86  return shared_ptr<T>();
87  }
88  }
89  private:
90  QReadWriteLock * const rwl;
91  bool locked;
92  };
93 }
94 
95 static shared_ptr<const std::pair<int,int> > lookupLegacyMapping( const QString & mimeType, PayloadBase * p ) {
96  MyReadLocker locker( legacyMapLock() );
97  const LegacyMap::const_iterator hit = typeInfoToMetaTypeIdMap()->constFind( mimeType );
98  if ( hit == typeInfoToMetaTypeIdMap()->constEnd() ) {
99  return shared_ptr<const std::pair<int,int> >();
100  }
101  const boost::shared_ptr<PayloadBase> sp( p, nodelete() );
102  const LegacyMap::mapped_type::const_iterator it = hit->find( sp );
103  if ( it == hit->end() ) {
104  return shared_ptr<const std::pair<int,int> >();
105  }
106 
107  return locker.makeUnlockingPointer( &it->second );
108 }
109 
110 // Change to something != RFC822 as soon as the server supports it
111 const char* Item::FullPayload = "RFC822";
112 
113 Item::Item()
114  : Entity( new ItemPrivate )
115 {
116 }
117 
118 Item::Item( Id id )
119  : Entity( new ItemPrivate( id ) )
120 {
121 }
122 
123 Item::Item( const QString & mimeType )
124  : Entity( new ItemPrivate )
125 {
126  d_func()->mMimeType = mimeType;
127 }
128 
129 Item::Item( const Item &other )
130  : Entity( other )
131 {
132 }
133 
134 Item::~Item()
135 {
136 }
137 
138 Item::Flags Item::flags() const
139 {
140  return d_func()->mFlags;
141 }
142 
143 void Item::setFlag( const QByteArray & name )
144 {
145  Q_D( Item );
146  d->mFlags.insert( name );
147  if ( !d->mFlagsOverwritten ) {
148  if ( d->mDeletedFlags.contains( name ) ) {
149  d->mDeletedFlags.remove( name );
150  } else {
151  d->mAddedFlags.insert( name );
152  }
153  }
154 }
155 
156 void Item::clearFlag( const QByteArray & name )
157 {
158  Q_D( Item );
159  d->mFlags.remove( name );
160  if ( !d->mFlagsOverwritten ) {
161  if ( d->mAddedFlags.contains( name ) ) {
162  d->mAddedFlags.remove( name );
163  } else {
164  d->mDeletedFlags.insert( name );
165  }
166  }
167 }
168 
169 void Item::setFlags( const Flags &flags )
170 {
171  Q_D( Item );
172  d->mFlags = flags;
173  d->mFlagsOverwritten = true;
174 }
175 
176 void Item::clearFlags()
177 {
178  Q_D( Item );
179  d->mFlags.clear();
180  d->mFlagsOverwritten = true;
181 }
182 
183 QDateTime Item::modificationTime() const
184 {
185  return d_func()->mModificationTime;
186 }
187 
188 void Item::setModificationTime( const QDateTime &datetime )
189 {
190  d_func()->mModificationTime = datetime;
191 }
192 
193 bool Item::hasFlag( const QByteArray & name ) const
194 {
195  return d_func()->mFlags.contains( name );
196 }
197 
198 void Item::setTags( const Tag::List& list )
199 {
200  Q_D( Item );
201  d->mTags = list;
202  d->mTagsOverwritten = true;
203 }
204 
205 void Item::setTag( const Tag &tag )
206 {
207  Q_D( Item );
208  d->mTags << tag;
209  if ( !d->mTagsOverwritten ) {
210  if ( d->mDeletedTags.contains( tag ) ) {
211  d->mDeletedTags.removeOne( tag );
212  } else {
213  d->mAddedTags << tag ;
214  }
215  }
216 }
217 
218 void Item::clearTags()
219 {
220  Q_D( Item );
221  d->mTags.clear();
222  d->mTagsOverwritten = true;
223 }
224 
225 void Item::clearTag( const Tag &tag )
226 {
227  Q_D( Item );
228  d->mTags.removeOne( tag );
229  if ( !d->mTagsOverwritten ) {
230  if ( d->mAddedTags.contains( tag ) ) {
231  d->mAddedTags.removeOne( tag );
232  } else {
233  d->mDeletedTags << tag;
234  }
235  }
236 }
237 
238 bool Item::hasTag( const Tag &tag ) const
239 {
240  Q_D( const Item );
241  return d->mTags.contains( tag );
242 }
243 
244 Tag::List Item::tags() const
245 {
246  Q_D( const Item );
247  return d->mTags;
248 }
249 
250 QSet<QByteArray> Item::loadedPayloadParts() const
251 {
252  return ItemSerializer::parts( *this );
253 }
254 
255 QByteArray Item::payloadData() const
256 {
257  int version = 0;
258  QByteArray data;
259  ItemSerializer::serialize( *this, FullPayload, data, version );
260  return data;
261 }
262 
263 void Item::setPayloadFromData( const QByteArray &data )
264 {
265  ItemSerializer::deserialize( *this, FullPayload, data, 0, false );
266 }
267 
268 void Item::clearPayload()
269 {
270  d_func()->mClearPayload = true;
271 }
272 
273 int Item::revision() const
274 {
275  return d_func()->mRevision;
276 }
277 
278 void Item::setRevision( int rev )
279 {
280  d_func()->mRevision = rev;
281 }
282 
283 Entity::Id Item::storageCollectionId() const
284 {
285  return d_func()->mCollectionId;
286 }
287 
288 void Item::setStorageCollectionId( Entity::Id collectionId )
289 {
290  d_func()->mCollectionId = collectionId;
291 }
292 
293 QString Item::mimeType() const
294 {
295  return d_func()->mMimeType;
296 }
297 
298 void Item::setSize( qint64 size )
299 {
300  Q_D( Item );
301  d->mSize = size;
302  d->mSizeChanged = true;
303 }
304 
305 qint64 Item::size() const
306 {
307  return d_func()->mSize;
308 }
309 
310 void Item::setMimeType( const QString & mimeType )
311 {
312  d_func()->mMimeType = mimeType;
313 }
314 
315 void Item::setGid( const QString &id )
316 {
317  d_func()->mGid = id;
318 }
319 
320 QString Item::gid() const
321 {
322  return d_func()->mGid;
323 }
324 
325 bool Item::hasPayload() const
326 {
327  return d_func()->hasMetaTypeId( -1 );
328 }
329 
330 KUrl Item::url( UrlType type ) const
331 {
332  KUrl url;
333  url.setProtocol( QString::fromLatin1( "akonadi" ) );
334  url.addQueryItem( QLatin1String( "item" ), QString::number( id() ) );
335 
336  if ( type == UrlWithMimeType ) {
337  url.addQueryItem( QLatin1String( "type" ), mimeType() );
338  }
339 
340  return url;
341 }
342 
343 Item Item::fromUrl( const KUrl &url )
344 {
345  if ( url.protocol() != QLatin1String( "akonadi" ) ) {
346  return Item();
347  }
348 
349  const QString itemStr = url.queryItem( QLatin1String( "item" ) );
350  bool ok = false;
351  Item::Id itemId = itemStr.toLongLong( &ok );
352  if ( !ok ) {
353  return Item();
354  }
355 
356  return Item( itemId );
357 }
358 
359 namespace {
360  class Dummy {};
361 }
362 
363 Q_GLOBAL_STATIC( Payload<Dummy>, dummyPayload )
364 
365 PayloadBase* Item::payloadBase() const
366 {
367  Q_D( const Item );
368  d->tryEnsureLegacyPayload();
369  if ( d->mLegacyPayload ) {
370  return d->mLegacyPayload.get();
371  } else {
372  return dummyPayload();
373  }
374 }
375 
376 void ItemPrivate::tryEnsureLegacyPayload() const
377 {
378  if ( !mLegacyPayload ) {
379  for ( PayloadContainer::const_iterator it = mPayloads.begin(), end = mPayloads.end() ; it != end ; ++it ) {
380  if ( lookupLegacyMapping( mMimeType, it->payload.get() ) ) {
381  mLegacyPayload = it->payload; // clones
382  }
383  }
384  }
385 }
386 
387 PayloadBase* Item::payloadBaseV2( int spid, int mtid ) const
388 {
389  return d_func()->payloadBaseImpl( spid, mtid );
390 }
391 
392 namespace {
393  class ConversionGuard {
394  const bool old;
395  bool & b;
396  public:
397  explicit ConversionGuard( bool & b )
398  : old( b ), b( b )
399  {
400  b = true;
401  }
402  ~ConversionGuard() {
403  b = old;
404  }
405  };
406 }
407 
408 bool Item::ensureMetaTypeId( int mtid ) const
409 {
410  Q_D( const Item );
411  // 0. Nothing there - nothing to convert from, either
412  if ( d->mPayloads.empty() ) {
413  return false;
414  }
415 
416  // 1. Look whether we already have one:
417  if ( d->hasMetaTypeId( mtid ) ) {
418  return true;
419  }
420 
421  // recursion detection (shouldn't trigger, but does if the
422  // serialiser plugins are acting funky):
423  if ( d->mConversionInProgress ) {
424  return false;
425  }
426 
427  // 2. Try to create one by conversion from a different representation:
428  try {
429  const ConversionGuard guard( d->mConversionInProgress );
430  Item converted = ItemSerializer::convert( *this, mtid );
431  return d->movePayloadFrom( converted.d_func(), mtid );
432  } catch ( const std::exception & e ) {
433  kDebug() << "conversion threw:" << e.what();
434  return false;
435  } catch ( ... ) {
436  kDebug() << "conversion threw something not derived from std::exception: fix the program!";
437  return false;
438  }
439 }
440 
441 static QString format_type( int spid, int mtid ) {
442  return QString::fromLatin1( "sp(%1)<%2>" )
443  .arg( spid ).arg( QLatin1String( QMetaType::typeName( mtid ) ) );
444 }
445 
446 static QString format_types( const PayloadContainer & c ) {
447  QStringList result;
448  for ( PayloadContainer::const_iterator it = c.begin(), end = c.end() ; it != end ; ++it ) {
449  result.push_back( format_type( it->sharedPointerId, it->metaTypeId ) );
450  }
451  return result.join( QLatin1String( ", " ) );
452 }
453 
454 #if 0
455 QString Item::payloadExceptionText( int spid, int mtid ) const
456 {
457  Q_D( const Item );
458  if ( d->mPayloads.empty() ) {
459  return QLatin1String( "No payload set" );
460  } else {
461  return QString::fromLatin1( "Wrong payload type (requested: %1; present: %2" )
462  .arg( format_type( spid, mtid ), format_types( d->mPayloads ) );
463  }
464 }
465 #else
466 void Item::throwPayloadException( int spid, int mtid ) const
467 {
468  Q_D( const Item );
469  if ( d->mPayloads.empty() ) {
470  throw PayloadException( "No payload set" );
471  } else {
472  throw PayloadException( QString::fromLatin1( "Wrong payload type (requested: %1; present: %2" )
473  .arg( format_type( spid, mtid ), format_types( d->mPayloads ) ) );
474  }
475 }
476 #endif
477 
478 void Item::setPayloadBase( PayloadBase* p )
479 {
480  d_func()->setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase>( p ) );
481 }
482 
483 void ItemPrivate::setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p )
484 {
485  if ( const shared_ptr<const std::pair<int,int> > pair = lookupLegacyMapping( mMimeType, p.get() ) ) {
486  std::auto_ptr<PayloadBase> clone;
487  if ( p.get() ) {
488  clone.reset( p->clone() );
489  }
490  setPayloadBaseImpl( pair->first, pair->second, p, false );
491  mLegacyPayload.reset( clone.release() );
492  } else {
493  mPayloads.clear();
494  mLegacyPayload.reset( p.release() );
495  }
496 }
497 
498 void Item::setPayloadBaseV2( int spid, int mtid, std::auto_ptr<PayloadBase> p )
499 {
500  d_func()->setPayloadBaseImpl( spid, mtid, p, false );
501 }
502 
503 void Item::addPayloadBaseVariant( int spid, int mtid, std::auto_ptr<PayloadBase> p ) const
504 {
505  d_func()->setPayloadBaseImpl( spid, mtid, p, true );
506 }
507 
508 QSet<QByteArray> Item::cachedPayloadParts() const
509 {
510  Q_D(const Item);
511  return d->mCachedPayloadParts;
512 }
513 
514 void Item::setCachedPayloadParts(const QSet< QByteArray > &cachedParts)
515 {
516  Q_D(Item);
517  d->mCachedPayloadParts = cachedParts;
518 }
519 
520 QSet<QByteArray> Item::availablePayloadParts() const
521 {
522  return ItemSerializer::availableParts( *this );
523 }
524 
525 QVector<int> Item::availablePayloadMetaTypeIds() const
526 {
527  QVector<int> result;
528  Q_D( const Item );
529  result.reserve( d->mPayloads.size() );
530  // Stable Insertion Sort - N is typically _very_ low (1 or 2).
531  for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it ) {
532  result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
533  }
534  return result;
535 }
536 
537 void Item::apply( const Item &other )
538 {
539  if ( mimeType() != other.mimeType() || id() != other.id() ) {
540  kDebug() << "mimeType() = " << mimeType() << "; other.mimeType() = " << other.mimeType();
541  kDebug() << "id() = " << id() << "; other.id() = " << other.id();
542  Q_ASSERT_X( false, "Item::apply", "mimetype or id missmatch" );
543  }
544 
545  setRemoteId( other.remoteId() );
546  setRevision( other.revision() );
547  setRemoteRevision( other.remoteRevision() );
548  setFlags( other.flags() );
549  setTags( other.tags() );
550  setModificationTime( other.modificationTime() );
551  setSize( other.size() );
552  setParentCollection( other.parentCollection() );
553  setStorageCollectionId( other.storageCollectionId() );
554 
555  QList<QByteArray> attrs;
556  foreach ( Attribute *attribute, other.attributes() ) {
557  addAttribute( attribute->clone() );
558  attrs.append( attribute->type() );
559  }
560 
561  QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
562  while ( it.hasNext() ) {
563  it.next();
564  if ( !attrs.contains( it.key() ) ) {
565  delete it.value();
566  it.remove();
567  }
568  }
569 
570  ItemSerializer::apply( *this, other );
571  d_func()->resetChangeLog();
572 }
573 
574 AKONADI_DEFINE_PRIVATE( Item )
Akonadi::Entity::Id
qint64 Id
Describes the unique id type.
Definition: entity.h:65
Akonadi::Attribute
Provides interface for custom attributes for Entity.
Definition: attribute.h:138
Akonadi::ItemSerializer::convert
static Item convert(const Item &item, int metaTypeId)
Tries to convert the payload in item into type with metatype-id metaTypeId.
Definition: itemserializer.cpp:196
Akonadi::ItemSerializer::parts
static QSet< QByteArray > parts(const Item &item)
Returns a list of parts available in the item payload.
Definition: itemserializer.cpp:173
Akonadi::ItemSerializer::apply
static void apply(Item &item, const Item &other)
Throws ItemSerializerException on failure.
Definition: itemserializer.cpp:146
Akonadi::ItemSerializer::deserialize
static void deserialize(Item &item, const QByteArray &label, const QByteArray &data, int version, bool external)
throws ItemSerializerException on failure
Definition: itemserializer.cpp:84
Akonadi::Entity
The base class for Item and Collection.
Definition: entity.h:59
Akonadi::ItemPrivate
Definition: item_p.h:163
Akonadi::Tag
An Akonadi Tag.
Definition: tag.h:44
Akonadi::ItemSerializer::serialize
static void serialize(const Item &item, const QByteArray &label, QByteArray &data, int &version)
throws ItemSerializerException on failure
Definition: itemserializer.cpp:127
Akonadi::Attribute::clone
virtual Attribute * clone() const =0
Creates a copy of this attribute.
Akonadi::Attribute::type
virtual QByteArray type() const =0
Returns the type of the attribute.
Akonadi::ItemSerializer::availableParts
static QSet< QByteArray > availableParts(const Item &item)
Returns a list of parts available remotely in the item payload.
Definition: itemserializer.cpp:180
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Mon Jul 21 2014 08:03:53 by doxygen 1.8.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs-4.13.3 API Reference

Skip menu "kdepimlibs-4.13.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal