20 #include "blockalarmsattribute.h"
21 #include "etmcalendar.h"
22 #include "etmcalendar_p.h"
23 #include "incidencefetchjob_p.h"
24 #include "calendarmodel_p.h"
25 #include "kcolumnfilterproxymodel_p.h"
27 #include <akonadi/item.h>
28 #include <akonadi/session.h>
29 #include <akonadi/collection.h>
30 #include <akonadi/changerecorder.h>
31 #include <akonadi/itemfetchscope.h>
32 #include <akonadi/entitydisplayattribute.h>
33 #include <akonadi/entitymimetypefiltermodel.h>
34 #include <akonadi/entitytreemodel.h>
35 #include <KSelectionProxyModel>
36 #include <kcheckableproxymodel.h>
38 #include <QSortFilterProxyModel>
39 #include <QItemSelectionModel>
41 using namespace Akonadi;
42 using namespace KCalCore;
46 ETMCalendarPrivate::ETMCalendarPrivate( ETMCalendar *qq ) : CalendarBasePrivate( qq )
49 , mCheckableProxyModel( 0 )
54 void ETMCalendarPrivate::init()
73 mETM =
new CalendarModel( monitor, q );
74 mETM->setObjectName(
"ETM" );
78 connect( mETM, SIGNAL(rowsInserted(QModelIndex,
int,
int)),
79 SLOT(onRowsInserted(QModelIndex,
int,
int)) );
80 connect( mETM, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
81 SLOT(onDataChanged(QModelIndex,QModelIndex)) );
82 connect( mETM, SIGNAL(rowsMoved(QModelIndex,
int,
int,QModelIndex,
int)),
83 SLOT(onRowsMoved(QModelIndex,
int,
int,QModelIndex,
int)) );
84 connect( mETM, SIGNAL(rowsRemoved(QModelIndex,
int,
int)),
85 SLOT(onRowsRemoved(QModelIndex,
int,
int)) );
87 connect( mFilteredETM, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
88 SLOT(onDataChangedInFilteredModel(QModelIndex,QModelIndex)) );
89 connect( mFilteredETM, SIGNAL(layoutChanged()),
90 SLOT(onLayoutChangedInFilteredModel()) );
91 connect( mFilteredETM, SIGNAL(modelReset()),
92 SLOT(onModelResetInFilteredModel()) );
93 connect( mFilteredETM, SIGNAL(rowsInserted(QModelIndex,
int,
int)),
94 SLOT(onRowsInsertedInFilteredModel(QModelIndex,
int,
int)) );
95 connect( mFilteredETM, SIGNAL(rowsAboutToBeRemoved(QModelIndex,
int,
int)),
96 SLOT(onRowsAboutToBeRemovedInFilteredModel(QModelIndex,
int,
int)) );
101 void ETMCalendarPrivate::setupFilteredETM()
104 QSortFilterProxyModel *sortFilterProxy =
new QSortFilterProxyModel(
this );
105 sortFilterProxy->setObjectName(
"Sort" );
106 sortFilterProxy->setDynamicSortFilter(
true );
107 sortFilterProxy->setSortCaseSensitivity( Qt::CaseInsensitive );
108 sortFilterProxy->setSourceModel( mETM );
112 columnFilterProxy->setSourceModel( sortFilterProxy );
114 columnFilterProxy->setObjectName(
"Remove columns" );
117 QItemSelectionModel* selectionModel =
new QItemSelectionModel( columnFilterProxy );
118 selectionModel->setObjectName(
"Calendar Selection Model" );
121 mCheckableProxyModel =
new KCheckableProxyModel(
this );
122 mCheckableProxyModel->setSelectionModel( selectionModel );
123 mCheckableProxyModel->setSourceModel( columnFilterProxy );
124 mCheckableProxyModel->setObjectName(
"Add checkboxes" );
126 KSelectionProxyModel* selectionProxy =
new KSelectionProxyModel( selectionModel,
this );
127 selectionProxy->setObjectName(
"Only show items of selected collection" );
128 selectionProxy->setFilterBehavior( KSelectionProxyModel::ChildrenOfExactSelection );
129 selectionProxy->setSourceModel( mETM );
133 mFilteredETM->setSourceModel( selectionProxy );
134 mFilteredETM->setSortRole( CalendarModel::SortRole );
135 mFilteredETM->setObjectName(
"Show headers" );
138 ETMCalendarPrivate::~ETMCalendarPrivate()
142 void ETMCalendarPrivate::loadFromETM()
144 itemsAdded( itemsFromModel( mETM ) );
147 void ETMCalendarPrivate::clear()
149 mCollectionMap.clear();
151 itemsRemoved( mItemById.values() );
152 Q_ASSERT( mItemById.isEmpty() );
153 Q_ASSERT( mItemIdByUid.isEmpty() );
158 Akonadi::Item::List ETMCalendarPrivate::itemsFromModel(
const QAbstractItemModel *model,
159 const QModelIndex &parentIndex,
162 const int endRow = end >= 0 ? end : model->rowCount( parentIndex ) - 1;
163 Akonadi::Item::List items;
165 QModelIndex i = model->index( row, 0, parentIndex );
166 while ( row <= endRow ) {
167 const Akonadi::Item item = itemFromIndex( i );
168 if ( item.hasPayload<KCalCore::Incidence::Ptr>() ) {
171 const QModelIndex childIndex = i.child( 0, 0 );
172 if ( childIndex.isValid() ) {
173 items << itemsFromModel( model, i );
177 i = i.sibling( row, 0 );
183 const QModelIndex &parentIndex,
186 const int endRow = end >= 0 ? end : model->rowCount( parentIndex ) - 1;
189 QModelIndex i = model->index( row, 0, parentIndex );
190 while ( row <= endRow ) {
193 collections << collection;
194 QModelIndex childIndex = i.child( 0, 0 );
195 if ( childIndex.isValid() ) {
196 collections << collectionsFromModel( model, i );
200 i = i.sibling( row, 0 );
205 Akonadi::Item ETMCalendarPrivate::itemFromIndex(
const QModelIndex &idx )
208 item.setParentCollection(
213 void ETMCalendarPrivate::itemsAdded(
const Akonadi::Item::List &items )
215 foreach(
const Akonadi::Item &item, items ) {
216 internalInsert( item );
218 emit q->calendarChanged();
221 void ETMCalendarPrivate::itemsRemoved(
const Akonadi::Item::List &items )
223 foreach(
const Akonadi::Item &item, items ) {
224 internalRemove( item );
226 emit q->calendarChanged();
234 void ETMCalendarPrivate::onRowsInserted(
const QModelIndex &index,
241 mCollectionMap[collection.
id()] = collection;
244 if ( !collections.isEmpty() )
245 emit q->collectionsAdded( collections );
248 void ETMCalendarPrivate::onRowsRemoved(
const QModelIndex &index,
int start,
int end )
252 mCollectionMap.remove( collection.
id() );
255 if ( !collections.isEmpty() )
256 emit q->collectionsRemoved( collections );
259 void ETMCalendarPrivate::onDataChanged(
const QModelIndex &topLeft,
260 const QModelIndex &bottomRight )
263 Q_ASSERT( topLeft.row() <= bottomRight.row() );
264 const int endRow = bottomRight.row();
265 QModelIndex i( topLeft );
267 while ( row <= endRow ) {
271 mCollectionMap.insert( col.
id(), col );
277 void ETMCalendarPrivate::onRowsMoved(
const QModelIndex &sourceParent,
280 const QModelIndex &destinationParent,
284 Q_UNUSED( sourceParent );
285 Q_UNUSED( sourceStart );
286 Q_UNUSED( sourceEnd );
287 Q_UNUSED( destinationParent );
288 Q_UNUSED( destinationRow );
291 void ETMCalendarPrivate::onLayoutChangedInFilteredModel()
297 void ETMCalendarPrivate::onModelResetInFilteredModel()
303 void ETMCalendarPrivate::onDataChangedInFilteredModel(
const QModelIndex &topLeft,
304 const QModelIndex &bottomRight )
306 Q_ASSERT( topLeft.row() <= bottomRight.row() );
307 const int endRow = bottomRight.row();
308 QModelIndex i( topLeft );
310 while ( row <= endRow ) {
311 const Akonadi::Item item = itemFromIndex( i );
312 if ( item.isValid() ) {
313 Incidence::Ptr newIncidence = item.payload<KCalCore::Incidence::Ptr>();
314 Q_ASSERT( newIncidence );
315 Q_ASSERT( !newIncidence->uid().isEmpty() );
316 IncidenceBase::Ptr existingIncidence = q->incidence( newIncidence->uid() );
317 Q_ASSERT( existingIncidence );
320 mItemById.insert( item.id(), item );
322 *(existingIncidence.data()) = *( newIncidence.data() );
325 i = i.sibling( row, topLeft.column() );
327 emit q->calendarChanged();
330 void ETMCalendarPrivate::onRowsInsertedInFilteredModel(
const QModelIndex &index,
333 itemsAdded( itemsFromModel( mFilteredETM, index, start, end ) );
336 void ETMCalendarPrivate::onRowsAboutToBeRemovedInFilteredModel(
const QModelIndex &index,
339 itemsRemoved( itemsFromModel( mFilteredETM, index, start, end ) );
342 ETMCalendar::ETMCalendar() :
CalendarBase( new ETMCalendarPrivate( this ) )
348 ETMCalendar::~ETMCalendar()
355 Q_D(
const ETMCalendar );
356 return d->mCollectionMap.value(
id );
361 return hasRight( item( uid ), right );
370 return col.
rights() & right;
373 QAbstractItemModel *ETMCalendar::filteredModel()
const
375 Q_D(
const ETMCalendar );
376 return d->mFilteredETM;
379 QAbstractItemModel *ETMCalendar::unfilteredModel()
const
381 Q_D(
const ETMCalendar );
385 KCheckableProxyModel *ETMCalendar::checkableProxyModel()
const
387 Q_D(
const ETMCalendar );
388 return d->mCheckableProxyModel;
391 KCalCore::Alarm::List ETMCalendar::alarms(
const KDateTime &from,
393 bool excludeBlockedAlarms )
const
395 Q_D(
const ETMCalendar );
396 KCalCore::Alarm::List alarmList;
397 QHashIterator<Akonadi::Item::Id, Akonadi::Item> i( d->mItemById );
398 while ( i.hasNext() ) {
399 const Akonadi::Item item = i.next().value();
401 if ( excludeBlockedAlarms ) {
403 Akonadi::Collection parentCollection = d->mCollectionMap.value( item.storageCollectionId() );
409 KCalCore::Incidence::Ptr incidence;
410 if ( item.isValid() && item.hasPayload<KCalCore::Incidence::Ptr>() ) {
411 incidence = item.payload<KCalCore::Incidence::Ptr>();
420 if ( incidence->recurs() ) {
421 appendRecurringAlarms( alarmList, incidence, from, to );
423 appendAlarms( alarmList, incidence, from, to );
429 #include "etmcalendar.moc"
430 #include "etmcalendar_p.moc"
void fetchAttribute(const QByteArray &type, bool fetch=true)
Sets whether the attribute of the given type should be fetched.
void setSession(Akonadi::Session *session)
Sets the session used by the Monitor to communicate with the Akonadi server.
void setMimeTypeMonitored(const QString &mimetype, bool monitored=true)
Sets whether items of the specified mime type shall be monitored for changes.
void setCollectionMonitored(const Collection &collection, bool monitored=true)
Sets whether the specified collection shall be monitored for changes.
Represents a collection of PIM items.
Filter model to make only certain columns of a model visible.
void setItemFetchScope(const ItemFetchScope &fetchScope)
Sets the item fetch scope.
qint64 Id
Describes the unique id type.
A proxy model that filters entities by mime type.
void fetchFullPayload(bool fetch=true)
Sets whether the full payload shall be fetched.
static Collection root()
Returns the root collection.
A communication session with the Akonadi storage.
The parent collection of the entity.
void fetchCollection(bool enable)
Enables automatic fetching of changed collections from the Akonadi storage.
Id id() const
Returns the unique identifier of the entity.
Rights rights() const
Returns the rights the user has on the collection.
Specifies which parts of an item should be fetched from the Akonadi storage.
Header information for a list of items.
Right
Describes rights of a collection.
bool hasAttribute(const QByteArray &name) const
Returns true if the entity has an attribute of the given type name, false otherwise.
The base class for all akonadi aware calendars.
bool isValid() const
Returns whether the entity is valid.
QList< Collection > List
Describes a list of collections.
Attribute that stores the properties that are used to display an entity.
void setVisibleColumn(int column)
Convenience function.
Records and replays change notification.
An Attribute that marks that alarms from a calendar collection are blocked.