filtereddatamodel.cpp Example File

filtereddatamodel/src/filtereddatamodel.cpp

/* Copyright (c) 2012, 2013 BlackBerry Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/#include "filtereddatamodel.hpp"
FilteredDataModel::FilteredDataModel(bb::cascades::DataModel *sourceModel,QObject*parent)
: bb::cascades::DataModel(parent)
, m_sourceDataModel(sourceModel)
, m_expandedIndex(-1) // no header expanded
{
}
/*
* Return true if we are filtering this indexPath.
* Return false if we are using the underlying data as-is.
*/bool FilteredDataModel::isFiltered(constQVariantList& indexPath) const
{
return indexPath.size() ==1&&
indexPath[0].toInt() != m_expandedIndex;
}
/*
* Return the number of children.
* Defer to the underlying data model unless the header is filtered.
* Note: assumes m_sourceDataModel is initialized
*/int FilteredDataModel::childCount(constQVariantList& indexPath)
{
if (isFiltered(indexPath)) {
// Unexpanded headerreturn0;
}
return m_sourceDataModel->childCount(indexPath); // pointer always initialized
}
/*
* Return the number of children.
*
* Logically this routine is equivalent to:
* return childCount(indexPath) != 0
* But with some underlying data models it may be expensive to ask
* for the child count but fast to check if there are any children at all.
* So mimic the code of childCOunt to detect our exception,
* and pass the request along for everything else.
*/bool FilteredDataModel::hasChildren(constQVariantList& indexPath)
{
if (isFiltered(indexPath)) {
// Unexpanded headerreturnfalse;
}
return m_sourceDataModel->hasChildren(indexPath); // pointer always initialized
}
/*
* Return the data.
* The ListView will only call this for valid data, so just
* forward the request to the underlying data model.
* We could add defensive code here to ensure we only return
* underlying data for unfiltered data.
*/QVariant FilteredDataModel::data(constQVariantList& indexPath)
{
if (indexPath.size() ==1) { // header item// Enrich the original data of the source model with additional data about expanded stateQVariantMap data;
data["data"]= m_sourceDataModel->data(indexPath);
data["expanded"]= (indexPath[0]== m_expandedIndex);
return data;
} else {
// Pass through the data from the source modelreturn m_sourceDataModel->data(indexPath);
}
}
/*
* Return the item type.
* The ListView will only call this for valid data, so just
* forward the request to the underlying data model.
* We could add defensive code here to ensure we only return
* underlying data for unfiltered data.
*/QString FilteredDataModel::itemType(constQVariantList& indexPath)
{
return m_sourceDataModel->itemType(indexPath); // pointer always initialized
}
/*
* Expand or collapse the specified header.
* We only support one header expanded at a time, so expanding
* a different header will collapse the previous.
* Requests that keep us in the current state are ignored.
*/void FilteredDataModel::expandHeader(int headerIndex,bool expand)
{
if (!expand) {
if (headerIndex == m_expandedIndex) {
// Collapse the header
setExpandedHeader(-1);
}
} else {
setExpandedHeader(headerIndex);
}
}
bool FilteredDataModel::isHeaderExpanded(int headerIndex) const
{
return (headerIndex == m_expandedIndex);
}
/*
* Set the currently expanded header (or none if index == -1)
* Inform the ListView that we made a possibly large change,
* but only if we do make a change.
*/void FilteredDataModel::setExpandedHeader(int index)
{
if (m_expandedIndex != index) {
// Only emit if we actually make a change
m_expandedIndex = index;
emit itemsChanged(bb::cascades::DataModelChangeType::AddRemove);
}
}