[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-pim
Subject:    [Kde-pim] [patch] Basic item modification time support for items
From:       Bertjan Broeksema <b.broeksema () kdemail ! net>
Date:       2008-07-22 18:58:45
Message-ID: 200807222058.45950.b.broeksema () kdemail ! net
[Download RAW message or body]

For review.

These two patches add basic modification time support for items. Modification 
time is set at creation and modification. A test is added to 
kdepimlibs/akonadi/tests/itemstoretest.{h,cpp}.

Note: This patch does not add support for retrieving items with a modification 
stamp after some given stamp.

This patch also fixes that the item that is returned by ItemCreateJob::item() 
has ID 0 in stead of -1.

regards,

Bertjan Broeksema

["kdepimlibs-akonadi.dif" (text/x-diff)]

Index: itemcreatejob.cpp
===================================================================
--- itemcreatejob.cpp	(revision 836665)
+++ itemcreatejob.cpp	(working copy)
@@ -27,6 +27,8 @@
 #include "job_p.h"
 #include "protocolhelper.h"
 
+#include <QtCore/QDateTime>
+
 #include <kdebug.h>
 
 using namespace Akonadi;
@@ -43,6 +45,7 @@
     Item mItem;
     QSet<QByteArray> mParts;
     Item::Id mUid;
+    QDateTime mDatetime;
     QByteArray mData;
 };
 
@@ -129,6 +132,13 @@
                        << tag << data;
       }
     }
+    if ( int pos = data.indexOf( "DATETIME" ) ) {
+      int resultPos = ImapParser::parseDateTime( data, d->mDatetime, pos + 8 );
+      if ( resultPos == (pos + 8) ) {
+        kDebug( 5250 ) << "Invalid DATETIME response to APPEND command: "
+            << tag << data;
+      }
+    }
   }
 }
 
@@ -141,6 +151,8 @@
 
   Item item( d->mItem );
   item.setId( d->mUid );
+  item.setRevision( 0 );
+  item.setModificationTime( d->mDatetime );
 
   return item;
 }
Index: itemmodifyjob.cpp
===================================================================
--- itemmodifyjob.cpp	(revision 836665)
+++ itemmodifyjob.cpp	(working copy)
@@ -159,8 +159,18 @@
   }
   if ( _tag == d->mTag ) {
     if ( data.startsWith( "OK" ) ) {
+      QDateTime modificationDateTime;
+      if ( int pos = data.indexOf( "DATETIME" ) ) {
+        int resultPos = ImapParser::parseDateTime( data, modificationDateTime, pos + \
8 ); +        if ( resultPos == (pos + 8) ) {
+          kDebug( 5250 ) << "Invalid DATETIME response to STORE command: "
+              << _tag << data;
+        }
+      }
+
       // increase item revision of own copy of item
       d->mItem.setRevision( d->mItem.revision() + 1 );
+      d->mItem.setModificationTime( modificationDateTime );
       d->mItem.d_ptr->resetChangeLog();
     } else {
       setError( Unknown );
Index: tests/itemstoretest.cpp
===================================================================
--- tests/itemstoretest.cpp	(revision 836665)
+++ tests/itemstoretest.cpp	(working copy)
@@ -24,6 +24,7 @@
 #include <akonadi/attributefactory.h>
 #include <akonadi/collectionfetchjob.h>
 #include <akonadi/collectionselectjob.h>
+#include <akonadi/itemcreatejob.h>
 #include <akonadi/itemdeletejob.h>
 #include <akonadi/itemfetchjob.h>
 #include <akonadi/itemfetchscope.h>
@@ -322,4 +323,52 @@
   QVERIFY( !sjob->exec() );
 }
 
+void ItemStoreTest::testModificationTime()
+{
+  Item item;
+  item.setMimeType( "text/directory" );
+  QVERIFY( item.modificationTime().isNull() );
+
+  ItemCreateJob *job = new ItemCreateJob( item, res1_foo );
+  QVERIFY( job->exec() );
+
+  // The item should have a datetime set now.
+  item = job->item();
+  QVERIFY( !item.modificationTime().isNull() );
+  QDateTime initialDateTime = item.modificationTime();
+
+  // Fetch the same item again.
+  Item item2( item.id() );
+  ItemFetchJob *fjob = new ItemFetchJob( item2, this );
+  QVERIFY( fjob->exec() );
+  item2 = fjob->items().first();
+  QCOMPARE( initialDateTime, item2.modificationTime() );
+
+  // Lets wait 5 secs.
+  QTest::qWait( 5000 );
+
+  // Modify the item
+  ItemModifyJob *mjob = new ItemModifyJob( item );
+  item.attribute<TestAttribute>( Item::AddIfMissing )->data = "extra";
+  QVERIFY( mjob->exec() );
+
+  // The item should still have a datetime set and that date should be somewhere
+  // after the initialDateTime.
+  item = mjob->item();
+  QVERIFY( !item.modificationTime().isNull() );
+  QVERIFY( initialDateTime < item.modificationTime() );
+
+  // Fetch the item after modification.
+  Item item3( item.id() );
+  ItemFetchJob *fjob2 = new ItemFetchJob( item3, this );
+  QVERIFY( fjob2->exec() );
+
+  // item3 should have the same modification time as item.
+  item3 = fjob2->items().first();
+  QCOMPARE( item3.modificationTime(), item.modificationTime() );
+
+  // Clean up
+  ItemDeleteJob *idjob = new ItemDeleteJob( item, this );
+  QVERIFY( idjob->exec() );
+}
 #include "itemstoretest.moc"
Index: tests/itemstoretest.h
===================================================================
--- tests/itemstoretest.h	(revision 836665)
+++ tests/itemstoretest.h	(working copy)
@@ -38,6 +38,7 @@
     void testMultiPart();
     void testPartRemove();
     void testRevisionCheck();
+    void testModificationTime();
 };
 
 #endif
Index: item.cpp
===================================================================
--- item.cpp	(revision 836665)
+++ item.cpp	(working copy)
@@ -91,6 +91,16 @@
   d->mFlagsOverwritten = true;
 }
 
+QDateTime Item::modificationTime() const
+{
+  return d_func()->mModificationTime;
+}
+
+void Item::setModificationTime( const QDateTime &datetime )
+{
+  d_func()->mModificationTime = datetime;
+}
+
 bool Item::hasFlag( const QByteArray & name ) const
 {
   return d_func()->mFlags.contains( name );
Index: itemfetchjob.cpp
===================================================================
--- itemfetchjob.cpp	(revision 836665)
+++ itemfetchjob.cpp	(working copy)
@@ -33,6 +33,7 @@
 
 #include <kdebug.h>
 
+#include <QtCore/QDateTime>
 #include <QtCore/QStringList>
 #include <QtCore/QTimer>
 
@@ -167,6 +168,7 @@
       // create a new item object
       Item::Id uid = -1;
       int rev = -1;
+      QDateTime datetime;
       QString rid;
       QString mimeType;
 
@@ -178,20 +180,23 @@
           uid = value.toLongLong();
         else if ( key == "REV" )
           rev = value.toInt();
+        else if ( key == "DATETIME" )
+          ImapParser::parseDateTime( value, datetime );
         else if ( key == "REMOTEID" )
           rid = QString::fromUtf8( value );
         else if ( key == "MIMETYPE" )
           mimeType = QString::fromLatin1( value );
       }
 
-      if ( uid < 0 || rev < 0 || mimeType.isEmpty() ) {
-        kWarning( 5250 ) << "Broken fetch response: UID, RID, REV or MIMETYPE \
missing!"; +      if ( uid < 0 || rev < 0 || datetime.isNull() || mimeType.isEmpty() \
) { +        kWarning( 5250 ) << "Broken fetch response: UID, RID, REV, DATETIME or \
MIMETYPE missing!";  return;
       }
 
       Item item( uid );
       item.setRemoteId( rid );
       item.setRevision( rev );
+      item.setModificationTime( datetime );
       item.setMimeType( mimeType );
       if ( !item.isValid() )
         return;
@@ -200,7 +205,7 @@
       for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) {
         const QByteArray key = fetchResponse.value( i );
         // skip stuff we dealt with already
-        if ( key == "UID" || key == "REV" || key == "REMOTEID" || key == "MIMETYPE" \
) +        if ( key == "UID" || key == "REV" || key == "DATETIME" || key == \
"REMOTEID" || key == "MIMETYPE" )  continue;
         // flags
         if ( key == "FLAGS" ) {
Index: item.h
===================================================================
--- item.h	(revision 836665)
+++ item.h	(working copy)
@@ -121,6 +121,19 @@
     Flags flags() const;
 
     /**
+     * Returns the timestamp of the last modification of this item.
+     */
+    QDateTime modificationTime() const;
+
+    /**
+     * Sets the timestamp of the last modification of this item.
+     *
+     * @note Do not modify this value from within an application,
+     * it is updated automatically by the revision checking functions.
+     */
+    void setModificationTime( const QDateTime &datetime );
+
+    /**
      * Returns whether the flag with the given @p name is
      * set in the item.
      */
Index: item_p.h
===================================================================
--- item_p.h	(revision 836665)
+++ item_p.h	(working copy)
@@ -20,6 +20,7 @@
 #ifndef AKONADI_ITEM_P_H
 #define AKONADI_ITEM_P_H
 
+#include <QtCore/QDateTime>
 #include <QtCore/QMap>
 
 #include "entity_p.h"
@@ -37,6 +38,7 @@
       : EntityPrivate( id ),
         mPayload( 0 ),
         mRevision( -1 ),
+        mModificationTime(),
         mFlagsOverwritten( false )
     {
     }
@@ -46,6 +48,7 @@
     {
       mFlags = other.mFlags;
       mRevision = other.mRevision;
+      mModificationTime = other.mModificationTime;
       mMimeType = other.mMimeType;
       if ( other.mPayload )
         mPayload = other.mPayload->clone();
@@ -73,6 +76,7 @@
     PayloadBase*  mPayload;
     Item::Flags mFlags;
     int mRevision;
+    QDateTime mModificationTime;
     QString mMimeType;
     Item::Flags mAddedFlags;
     Item::Flags mDeletedFlags;


["kdesupport-akonadi.dif" (text/x-diff)]

Index: server/src/handler/append.cpp
===================================================================
--- server/src/handler/append.cpp	(revision 836660)
+++ server/src/handler/append.cpp	(working copy)
@@ -116,8 +116,14 @@
     if ( !mimeType.isValid() ) {
       return failureResponse( QString::fromLatin1( "Unknown mime type '%1'.").arg( \
QString::fromLatin1( mt ) ) );  }
+
+    if( m_dateTime == QDateTime() ) {
+      m_dateTime = QDateTime::currentDateTime();
+    }
+
     PimItem item;
     item.setRev( 0 );
+    item.setDatetime( m_dateTime );
 
     // wrap data into a part
     Part part;
@@ -144,9 +150,16 @@
     if ( !transaction.commit() )
         return failureResponse( "Unable to commit transaction." );
 
+    QString datetime = item.datetime().toString( QLatin1String( "dd-MMM-yyyy \
hh:mm:ss" ) ); +    datetime.append( QLatin1String( " +0000" ) );
+
+    QByteArray res( "[UIDNEXT " + QByteArray::number( item.id() ) + " " );
+    res.append( "DATETIME " + ImapParser::quote( datetime.toUtf8() ) );
+    res.append( ']' );
+
     response.setTag( tag() );
     response.setUserDefined();
-    response.setString( "[UIDNEXT " + QByteArray::number( item.id() ) + ']' );
+    response.setString( res );
     emit responseAvailable( response );
 
     response.setSuccess();
Index: server/src/handler/store.cpp
===================================================================
--- server/src/handler/store.cpp	(revision 836660)
+++ server/src/handler/store.cpp	(working copy)
@@ -85,6 +85,9 @@
   else if ( buffer == "NOREV" )
     revCheck   = false;
 
+  // Set the same modification time for each item.
+  QDateTime modificationtime = QDateTime::currentDateTime();
+
   for ( int i = 0; i < pimItems.count(); ++i ) {
     if ( revCheck ) {
       // check if revision number of given items and their database equivalents \
match @@ -95,7 +98,7 @@
 
     // update item revision
     pimItems[ i ].setRev( pimItems[ i ].rev() + 1 );
-    pimItems[ i ].setDatetime( QDateTime::currentDateTime() );
+    pimItems[ i ].setDatetime( modificationtime );
     if ( !pimItems[ i ].update() ) {
       return failureResponse( "Unable to update item revision" );
     }
@@ -210,9 +213,12 @@
   if ( !transaction.commit() )
     return failureResponse( "Cannot commit transaction." );
 
+  QString datetime = modificationtime.toString( QLatin1String( "dd-MMM-yyyy \
hh:mm:ss" ) ); +  datetime.append( QLatin1String( " +0000" ) );
+
   response.setTag( tag() );
   response.setSuccess();
-  response.setString( "STORE completed" );
+  response.setString( "DATETIME " + ImapParser::quote( datetime.toUtf8() ) + " STORE \
completed" );  
   emit responseAvailable( response );
   deleteLater();
Index: server/src/handler/fetch.cpp
===================================================================
--- server/src/handler/fetch.cpp	(revision 836660)
+++ server/src/handler/fetch.cpp	(working copy)
@@ -50,9 +50,10 @@
 
 static const int itemQueryIdColumn = 0;
 static const int itemQueryRevColumn = 1;
-static const int itemQueryRidColumn = 2;
-static const int itemQueryMimeTypeColumn = 3;
-static const int itemQueryResouceColumn = 4;
+static const int itemQueryDatetimeColumn = 2;
+static const int itemQueryRidColumn = 3;
+static const int itemQueryMimeTypeColumn = 4;
+static const int itemQueryResouceColumn = 5;
 
 static const int partQueryIdColumn = 0;
 static const int partQueryNameColumn = 1;
@@ -183,9 +184,15 @@
     while ( mItemQuery.query().isValid() ) {
       const qint64 pimItemId = mItemQuery.query().value( itemQueryIdColumn \
                ).toLongLong();
       const int pimItemRev = mItemQuery.query().value( itemQueryRevColumn ).toInt();
+      const QDateTime pimItemDatetime = mItemQuery.query().value( \
itemQueryDatetimeColumn ).toDateTime(); +
+      QString datetime = pimItemDatetime.toString( QLatin1String( "dd-MMM-yyyy \
hh:mm:ss" ) ); +      datetime.append( QLatin1String( " +0000" ) );
+
       QList<QByteArray> attributes;
       attributes.append( "UID " + QByteArray::number( pimItemId ) );
       attributes.append( "REV " + QByteArray::number( pimItemRev ) );
+      attributes.append( "DATETIME " + ImapParser::quote( datetime.toUtf8() ) );
       attributes.append( "REMOTEID " + ImapParser::quote( mItemQuery.query().value( \
                itemQueryRidColumn ).toString().toUtf8() ) );
       attributes.append( "MIMETYPE " + ImapParser::quote( mItemQuery.query().value( \
itemQueryMimeTypeColumn ).toString().toUtf8() ) );  
@@ -323,6 +330,7 @@
   // make sure the columns indexes here and in the constants defined above match
   mItemQuery.addColumn( PimItem::idFullColumnName() );
   mItemQuery.addColumn( PimItem::revFullColumnName() );
+  mItemQuery.addColumn( PimItem::datetimeFullColumnName() );
   mItemQuery.addColumn( PimItem::remoteIdFullColumnName() );
   mItemQuery.addColumn( MimeType::nameFullColumnName() );
   mItemQuery.addColumn( Resource::nameFullColumnName() );



_______________________________________________
KDE PIM mailing list kde-pim@kde.org
https://mail.kde.org/mailman/listinfo/kde-pim
KDE PIM home page at http://pim.kde.org/

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic