[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: KDE/kdepim/calendarsupport/next
From: Sergio Luis Martins <iamsergio () gmail ! com>
Date: 2010-10-25 23:42:40
Message-ID: 20101025234240.ECAD8AC897 () svn ! kde ! org
[Download RAW message or body]
SVN commit 1189823 by smartins:
Added an overload to History::recordDeletion( Item ):
History::recordDeletions( Item::List )
Now redoing something done with IncidenceChanger::deleteIncidences( Item::List ) will \
only need one ItemDeleteJob, not N.
M +73 -56 history.cpp
M +11 -0 history.h
M +5 -3 history_p.h
--- trunk/KDE/kdepim/calendarsupport/next/history.cpp #1189822:1189823
@@ -61,9 +61,9 @@
"recordCreation()", "Item must be valid and have Incidence payload." \
);
Entry entry;
- entry.itemId = item.id();
entry.changeType = IncidenceChanger2::ChangeTypeCreate;
- entry.newItem = item;
+ entry.newItems.append( item );
+ entry.newItems.append( Item() );
entry.atomicOperationId = atomicOperationId;
d->mLatestRevisionByItemId.insert( item.id(), item.revision() );
@@ -82,11 +82,10 @@
oldItem.id() == newItem.id(),
"recordChange()", "oldItem and newItem must be valid and have the same \
id" ); Entry entry;
- entry.itemId = newItem.id();
entry.changeType = IncidenceChanger2::ChangeTypeModify;
entry.atomicOperationId = atomicOperationId;
- entry.oldItem = oldItem;
- entry.newItem = newItem;
+ entry.oldItems.append( oldItem );
+ entry.newItems.append( newItem );
d->mLatestRevisionByItemId.insert( newItem.id(), newItem.revision() );
d->mUndoStack.push( entry );
@@ -98,15 +97,26 @@
void History::recordDeletion( const Akonadi::Item &item,
const uint atomicOperationId )
{
- Q_ASSERT_X( item.isValid() && item.hasPayload<Incidence::Ptr>(),
- "recordDeletion()", "Item must be valid and have an Incidence \
payload." ); + Item::List list;
+ list.append( item );
+ recordDeletions( list, atomicOperationId );
+}
+void History::recordDeletions( const Akonadi::Item::List &items,
+ const uint atomicOperationId )
+{
Entry entry;
- entry.itemId = item.id();
- entry.oldItem = item;
entry.changeType = IncidenceChanger2::ChangeTypeDelete;
entry.atomicOperationId = atomicOperationId;
+
+ foreach( const Akonadi::Item &item, items ) {
+ Q_ASSERT_X( item.isValid() && item.hasPayload<Incidence::Ptr>(),
+ "recordDeletion()", "Item must be valid and have an Incidence \
payload." ); + //cleanup
d->mLatestRevisionByItemId.remove( item.id() );
+ entry.oldItems.append( item );
+ entry.newItems.append( Item() );
+ }
d->mUndoStack.push( entry );
d->mRedoStack.clear();
@@ -208,40 +218,27 @@
void History::Private::updateIds( Item::Id oldId, Item::Id newId )
{
- for ( int i = 0; i < mUndoStack.count(); ++i ) {
- if ( mUndoStack[i].itemId == oldId ) {
+ QList<QStack<Entry>*> stacks;
+ stacks << &mUndoStack << &mRedoStack;
- mUndoStack[i].itemId = newId;
-
- if ( mUndoStack[i].oldItem.isValid() )
- mUndoStack[i].oldItem.setId( newId );
-
- if ( mUndoStack[i].newItem.isValid() )
- mUndoStack[i].newItem.setId( newId );
+ for ( int i = 0; i < stacks.count(); ++i ) {
+ QStack<Entry>::iterator j;
+ for ( j = stacks[0]->begin(); j != stacks[i]->end(); ++j ) {
+ Item::List::iterator k;
+ for ( k = (*j).oldItems.begin(); k != (*j).oldItems.end(); ++k ) {
+ if ( (*k).id() == oldId ) {
+ (*k).setId( newId );
}
}
- for ( int i = 0; i < mRedoStack.count(); ++i ) {
- if ( mRedoStack[i].itemId == oldId ) {
-
- mRedoStack[i].itemId = newId;
-
- if ( mRedoStack[i].oldItem.isValid() )
- mRedoStack[i].oldItem.setId( newId );
-
- if ( mRedoStack[i].newItem.isValid() )
- mRedoStack[i].newItem.setId( newId );
+ for ( k = (*j).newItems.begin(); k != (*j).newItems.end(); ++k ) {
+ if ( (*k).id() == oldId ) {
+ (*k).setId( newId );
}
}
-
- if ( mEntryInProgress.oldItem.isValid() )
- mEntryInProgress.oldItem.setId( newId );
-
- if ( mEntryInProgress.newItem.isValid() )
- mEntryInProgress.newItem.setId( newId );
-
- mEntryInProgress.itemId = newId;
}
+ }
+}
bool History::Private::doIt( const Entry &entry, OperationType type, QWidget *parent \
) {
@@ -259,6 +256,17 @@
break;
case IncidenceChanger2::ChangeTypeDelete:
e.changeType = IncidenceChanger2::ChangeTypeCreate;
+
+ if ( e.oldItems.count() > 1 && e.atomicOperationId != 0 ) {
+ /** We're undoing a bulk delete.
+ ItemDeleteJob supports deleting a list of items,But while undoing \
that, + we can't just use one ItemCreateJob, because it's ctor only \
accepts one item, + we must create an ItemCreateJob for each.
+
+ So lets group all creations, so, in case one item fails, we can \
rollback. + */
+ e.atomicOperationId = mChanger->startAtomicOperation();
+ }
break;
case IncidenceChanger2::ChangeTypeModify:
break;
@@ -267,42 +275,50 @@
}
// Swap old item with new item.
- Akonadi::Item oldItem2 = e.oldItem;
- e.oldItem = e.newItem;
- e.newItem = oldItem2;
+ Akonadi::Item::List oldItems2 = e.oldItems;
+ e.oldItems = e.newItems;
+ e.newItems = oldItems2;
}
- Incidence::Ptr oldPayload = CalendarSupport::incidence( e.oldItem );
- Incidence::Ptr newPayload = CalendarSupport::incidence( e.newItem );
-
- bool result;
+ int changeId = -1;
if ( e.changeType == IncidenceChanger2::ChangeTypeCreate ) {
- Akonadi::Collection collection = e.newItem.parentCollection();
- result = mChanger->createIncidence( newPayload, collection, e.atomicOperationId,
+ foreach( const Item &item, e.newItems ) {
+ Incidence::Ptr newPayload = CalendarSupport::incidence( item );
+ // TODO: don't overwrite result
+ const Akonadi::Collection collection = item.parentCollection();
+ changeId = mChanger->createIncidence( newPayload, collection, \
e.atomicOperationId,
false, /* don't record to history, we're on \
it */ parent );
+ mItemIdByChangeId[e.changeId] = item.id();
+ }
// now wait for mChanger to call our slot.
} else if ( e.changeType == IncidenceChanger2::ChangeTypeDelete ) {
- Akonadi::Item item = e.oldItem;
- result = mChanger->deleteIncidence( item, e.atomicOperationId,
+ changeId = mChanger->deleteIncidences( e.oldItems,
+ e.atomicOperationId,
false, /* don't record to history, we're on \
it */ parent );
// now wait for mChanger to call our slot.
} else if ( e.changeType == IncidenceChanger2::ChangeTypeModify ) {
- if ( mLatestRevisionByItemId.contains( e.itemId ) ) {
- e.newItem.setRevision( mLatestRevisionByItemId[e.itemId] );
+ // ItemModifyJob doesn't support a bulk operation, so modify operations will \
only have one + // element, therefore first().
+ Item newItem = e.newItems.first();
+
+ if ( mLatestRevisionByItemId.contains( newItem.id() ) ) {
+ newItem.setRevision( mLatestRevisionByItemId[newItem.id()] );
}
- result = mChanger->modifyIncidence( e.newItem, e.oldItem, e.atomicOperationId,
+ changeId = mChanger->modifyIncidence( newItem, Item(), e.atomicOperationId,
false, /* don't record to history, we're on \
it */ parent );
// now wait for mChanger to call our slot.
} else {
- result = false;
+ changeId = -1;
Q_ASSERT_X( false, "History::Private::doIt()", "Must have at least one payload" \
); }
- if ( !result ) {
+ mEntryInProgress.changeId = changeId;
+
+ if ( changeId == -1 ) {
// Don't i18n yet, only after refactoring IncidenceChanger.
mLastErrorString = "Error in incidence changer, didn't even fire the job";
mOperationTypeInProgress = TypeNone;
@@ -310,7 +326,7 @@
updateWidgets();
}
- return result;
+ return changeId != -1;
}
void History::Private::deleteFinished( int changeId,
@@ -345,13 +361,14 @@
const History::ResultCode resultCode = success ? History::ResultCodeSuccess :
History::ResultCodeError;
+ finishOperation( resultCode, errorMessage );
+
if ( success ) {
// Por comentário.
- updateIds( mEntryInProgress.itemId /*old*/, item.id() /*new*/ );
+ updateIds( mItemIdByChangeId[changeId] /*old*/, item.id() /*new*/ );
+ mItemIdByChangeId.remove( changeId );
mLatestRevisionByItemId.insert( item.id(), item.revision() );
}
-
- finishOperation( resultCode, errorMessage );
}
void History::Private::modifyFinished( int changeId,
--- trunk/KDE/kdepim/calendarsupport/next/history.h #1189822:1189823
@@ -121,6 +121,17 @@
const uint atomicOperationId = 0 );
/**
+ Pushes a list of incidence deletions into the undo stack. The deletions can \
be undone calling + undo() once.
+
+ @param items The list of items to delete. All items must be valid.
+ @param atomicOperation If != 0, specifies which group of changes this change \
belongs too. + Will be useful for atomic undoing/redoing, not \
implemented yet. + */
+ void recordDeletions( const Akonadi::Item::List &items,
+ const uint atomicOperationId = 0 );
+
+ /**
Convenience method for disabling the undo/redo button when jobs are in \
progress, so callers don't have to write signal/slot/connect logic for this.
--- trunk/KDE/kdepim/calendarsupport/next/history_p.h #1189822:1189823
@@ -46,11 +46,12 @@
struct Entry {
// An history entry is something that can be done/undone
- Akonadi::Item oldItem;
- Akonadi::Item newItem;
- Akonadi::Item::Id itemId;
+ Akonadi::Item::List oldItems;
+ Akonadi::Item::List newItems;
+
IncidenceChanger2::ChangeType changeType;
uint atomicOperationId;
+ int changeId;
};
class History::Private : public QObject {
@@ -82,6 +83,7 @@
QString mLastErrorString;
QHash<Akonadi::Item::Id,int> mLatestRevisionByItemId;
+ QHash<int,Akonadi::Item::Id> mItemIdByChangeId;
QWidget *mParent;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic