2 * itemlistmodel.cpp - Akonadi item models
4 * Copyright © 2007-2012 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "itemlistmodel.h"
22 #include "collectionmodel.h"
24 #include <kalarmcal/kaevent.h>
26 #include <kselectionproxymodel.h>
28 using namespace Akonadi
;
31 /*=============================================================================
32 = Class: ItemListModel
33 = Filter proxy model containing all items (alarms/templates) of specified mime
34 = types in enabled collections.
35 =============================================================================*/
36 ItemListModel::ItemListModel(CalEvent::Types allowed
, QObject
* parent
)
37 : EntityMimeTypeFilterModel(parent
),
38 mAllowedTypes(allowed
),
41 KSelectionProxyModel
* selectionModel
= new KSelectionProxyModel(CollectionControlModel::instance()->selectionModel(), this);
42 selectionModel
->setSourceModel(AkonadiModel::instance());
43 selectionModel
->setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection
);
44 setSourceModel(selectionModel
);
46 addMimeTypeExclusionFilter(Collection::mimeType());
47 setHeaderGroup(EntityTreeModel::ItemListHeaders
);
50 QStringList mimeTypes
= CalEvent::mimeTypes(allowed
);
51 foreach (const QString
& mime
, mimeTypes
)
52 addMimeTypeInclusionFilter(mime
);
54 setHeaderGroup(EntityTreeModel::ItemListHeaders
);
55 setSortRole(AkonadiModel::SortRole
);
56 setDynamicSortFilter(true);
57 connect(this, &ItemListModel::rowsInserted
, this, &ItemListModel::slotRowsInserted
);
58 connect(this, &ItemListModel::rowsRemoved
, this, &ItemListModel::slotRowsRemoved
);
59 connect(AkonadiModel::instance(), &AkonadiModel::collectionStatusChanged
,
60 this, &ItemListModel::collectionStatusChanged
);
63 int ItemListModel::columnCount(const QModelIndex
& /*parent*/) const
65 return AkonadiModel::ColumnCount
;
68 /******************************************************************************
69 * Called when rows have been inserted into the model.
71 void ItemListModel::slotRowsInserted()
73 if (!mHaveEvents
&& rowCount())
76 Q_EMIT
haveEventsStatus(true);
80 /******************************************************************************
81 * Called when rows have been deleted from the model.
83 void ItemListModel::slotRowsRemoved()
85 if (mHaveEvents
&& !rowCount())
88 Q_EMIT
haveEventsStatus(false);
92 /******************************************************************************
93 * Called when a collection parameter or status has changed.
94 * If the collection's enabled status has changed, re-filter the list to add or
97 void ItemListModel::collectionStatusChanged(const Collection
& collection
, AkonadiModel::Change change
, const QVariant
&, bool inserted
)
100 if (!collection
.isValid())
102 if (change
== AkonadiModel::Enabled
)
104 // Ensure that items for a newly enabled collection are always ordered
105 // correctly. Note that invalidateFilter() is not adequate for this.
110 bool ItemListModel::filterAcceptsRow(int sourceRow
, const QModelIndex
& sourceParent
) const
112 if (!EntityMimeTypeFilterModel::filterAcceptsRow(sourceRow
, sourceParent
))
114 // Get the alarm type of the item
115 QModelIndex sourceIndex
= sourceModel()->index(sourceRow
, 0, sourceParent
);
116 CalEvent::Type type
= static_cast<CalEvent::Type
>(sourceModel()->data(sourceIndex
, AkonadiModel::StatusRole
).toInt());
117 Collection parent
= sourceIndex
.data(AkonadiModel::ParentCollectionRole
).value
<Collection
>();
118 return CollectionControlModel::isEnabled(parent
, type
);
122 QModelIndex
ItemListModel::index(int row
, int column
, const QModelIndex
& parent
) const
124 if (parent
.isValid())
125 return QModelIndex();
126 return createIndex(row
, column
, mEvents
[row
]);
129 bool ItemListModel::setData(const QModelIndex
& ix
, const QVariant
&, int role
)
131 if (ix
.isValid() && role
== Qt::EditRole
)
135 Q_EMIT
dataChanged(index(row
, 0), index(row
, AkonadiModel::ColumnCount
- 1));
142 Qt::ItemFlags
ItemListModel::flags(const QModelIndex
& index
) const
144 if (!index
.isValid())
145 return Qt::ItemIsEnabled
;
146 return Qt::ItemIsEnabled
| Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsDragEnabled
;
149 /******************************************************************************
150 * Return the index to a specified event.
152 QModelIndex
ItemListModel::eventIndex(Item::Id itemId
) const
154 QModelIndexList list
= match(QModelIndex(), AkonadiModel::ItemIdRole
, itemId
, 1, Qt::MatchExactly
| Qt::MatchRecursive
);
156 return QModelIndex();
157 return index(list
[0].row(), 0, list
[0].parent());
160 /******************************************************************************
161 * Return the event in a specified row.
163 KAEvent
ItemListModel::event(int row
) const
165 return event(index(row
, 0));
168 /******************************************************************************
169 * Return the event referred to by an index.
171 KAEvent
ItemListModel::event(const QModelIndex
& index
) const
173 return static_cast<AkonadiModel
*>(sourceModel())->event(mapToSource(index
));
176 /******************************************************************************
177 * Check whether the model contains any events.
179 bool ItemListModel::haveEvents() const
185 /*=============================================================================
186 = Class: AlarmListModel
187 = Filter proxy model containing all alarms (not templates) of specified mime
188 = types in enabled collections.
189 Equivalent to AlarmListFilterModel
190 =============================================================================*/
191 AlarmListModel
* AlarmListModel::mAllInstance
= Q_NULLPTR
;
193 AlarmListModel::AlarmListModel(QObject
* parent
)
194 : ItemListModel(CalEvent::ACTIVE
| CalEvent::ARCHIVED
, parent
),
195 mFilterTypes(CalEvent::ACTIVE
| CalEvent::ARCHIVED
)
199 AlarmListModel::~AlarmListModel()
201 if (this == mAllInstance
)
202 mAllInstance
= Q_NULLPTR
;
205 AlarmListModel
* AlarmListModel::all()
209 mAllInstance
= new AlarmListModel(AkonadiModel::instance());
210 mAllInstance
->sort(TimeColumn
, Qt::AscendingOrder
);
215 void AlarmListModel::setEventTypeFilter(CalEvent::Types types
)
217 // Ensure that the filter isn't applied to the 'all' instance, and that
218 // 'types' doesn't include any disallowed alarm types
220 types
= includedTypes();
221 if (this != mAllInstance
222 && types
!= mFilterTypes
&& (types
& includedTypes()) == types
)
224 mFilterTypes
= types
;
229 bool AlarmListModel::filterAcceptsRow(int sourceRow
, const QModelIndex
& sourceParent
) const
231 if (!ItemListModel::filterAcceptsRow(sourceRow
, sourceParent
))
233 if (mFilterTypes
== CalEvent::EMPTY
)
235 int type
= sourceModel()->data(sourceModel()->index(sourceRow
, 0, sourceParent
), AkonadiModel::StatusRole
).toInt();
236 return static_cast<CalEvent::Type
>(type
) & mFilterTypes
;
239 bool AlarmListModel::filterAcceptsColumn(int sourceCol
, const QModelIndex
&) const
241 return (sourceCol
!= AkonadiModel::TemplateNameColumn
);
244 QVariant
AlarmListModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
246 if (orientation
== Qt::Horizontal
)
248 if (section
< 0 || section
>= ColumnCount
)
251 return ItemListModel::headerData(section
, orientation
, role
);
255 /*=============================================================================
256 = Class: TemplateListModel
257 = Filter proxy model containing all alarm templates for specified alarm types
258 = in enabled collections.
259 Equivalent to TemplateListFilterModel
260 =============================================================================*/
261 TemplateListModel
* TemplateListModel::mAllInstance
= Q_NULLPTR
;
263 TemplateListModel::TemplateListModel(QObject
* parent
)
264 : ItemListModel(CalEvent::TEMPLATE
, parent
),
265 mActionsEnabled(KAEvent::ACT_ALL
),
266 mActionsFilter(KAEvent::ACT_ALL
)
270 TemplateListModel::~TemplateListModel()
272 if (this == mAllInstance
)
273 mAllInstance
= Q_NULLPTR
;
276 TemplateListModel
* TemplateListModel::all()
280 mAllInstance
= new TemplateListModel(AkonadiModel::instance());
281 mAllInstance
->sort(TemplateNameColumn
, Qt::AscendingOrder
);
286 void TemplateListModel::setAlarmActionFilter(KAEvent::Actions types
)
288 // Ensure that the filter isn't applied to the 'all' instance.
289 if (this != mAllInstance
&& types
!= mActionsFilter
)
291 mActionsFilter
= types
;
296 void TemplateListModel::setAlarmActionsEnabled(KAEvent::Actions types
)
298 // Ensure that the setting isn't applied to the 'all' instance.
299 if (this != mAllInstance
&& types
!= mActionsEnabled
)
301 mActionsEnabled
= types
;
306 bool TemplateListModel::filterAcceptsRow(int sourceRow
, const QModelIndex
& sourceParent
) const
308 if (!ItemListModel::filterAcceptsRow(sourceRow
, sourceParent
))
310 if (mActionsFilter
== KAEvent::ACT_ALL
)
312 QModelIndex sourceIndex
= sourceModel()->index(sourceRow
, 0, sourceParent
);
313 KAEvent::Actions actions
= static_cast<KAEvent::Actions
>(sourceModel()->data(sourceIndex
, AkonadiModel::AlarmActionsRole
).toInt());
314 return actions
& mActionsFilter
;
317 bool TemplateListModel::filterAcceptsColumn(int sourceCol
, const QModelIndex
&) const
319 return sourceCol
== AkonadiModel::TemplateNameColumn
320 || sourceCol
== AkonadiModel::TypeColumn
;
323 QVariant
TemplateListModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
325 if (orientation
== Qt::Horizontal
)
330 section
= AkonadiModel::TypeColumn
;
332 case TemplateNameColumn
:
333 section
= AkonadiModel::TemplateNameColumn
;
339 return ItemListModel::headerData(section
, orientation
, role
);
342 Qt::ItemFlags
TemplateListModel::flags(const QModelIndex
& index
) const
344 Qt::ItemFlags f
= sourceModel()->flags(mapToSource(index
));
345 if (mActionsEnabled
== KAEvent::ACT_ALL
)
347 KAEvent::Actions actions
= static_cast<KAEvent::Actions
>(ItemListModel::data(index
, AkonadiModel::AlarmActionsRole
).toInt());
348 if (!(actions
& mActionsEnabled
))
349 f
= static_cast<Qt::ItemFlags
>(f
& ~(Qt::ItemIsEnabled
| Qt::ItemIsSelectable
));