/* * Copyright 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authors: * Renato Araujo Oliveira Filho */ extern "C" { #include } #include "flatmenuproxymodel.h" #include #include FlatMenuProxyModel::FlatMenuProxyModel(QAbstractItemModel *source) : QAbstractProxyModel(source), m_rowCount(0) { m_model = new QDBusMenuModel; setSourceModel(m_model); } /*! \internal */ FlatMenuProxyModel::~FlatMenuProxyModel() { delete m_model; } void FlatMenuProxyModel::setSourceModel(QAbstractItemModel *source) { if (sourceModel()) { QAbstractItemModel *oldSource = sourceModel(); if (oldSource == source) { return; } oldSource->disconnect(this); } QAbstractProxyModel::setSourceModel(source); if (source) { // FIXME - not working correctly with dynamic inserts/removes connect(source, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), SLOT(onModelAboutToBeReset())); connect(source, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(onModelReset())); connect(source, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), SLOT(onModelAboutToBeReset())); connect(source, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(onModelReset())); connect(source, SIGNAL(modelAboutToBeReset()), SLOT(onModelAboutToBeReset())); connect(source, SIGNAL(modelReset()), SLOT(onModelReset())); connect(source, SIGNAL(statusChanged(DBusEnums::ConnectionStatus)), SIGNAL(statusChanged())); // initiliaze rowCount QModelIndex lastItem = source->index(source->rowCount() - 1, 0); m_rowCount = recursiveRowCount(lastItem); } else { m_rowCount = 0; } Q_EMIT countChanged(); } void FlatMenuProxyModel::setBusName(const QString &busName) { m_model->setBusName(busName); } QString FlatMenuProxyModel::busName() const { return m_model->busName(); } void FlatMenuProxyModel::setObjectPath(const QString &busPath) { m_model->setObjectPath(busPath); } QString FlatMenuProxyModel::objectPath() const { return m_model->objectPath(); } int FlatMenuProxyModel::status() const { return m_model->status(); } DBusEnums::BusType FlatMenuProxyModel::busType() const { return m_model->busType(); } void FlatMenuProxyModel::setIntBusType(int type) { m_model->setBusType((DBusEnums::BusType) type); } void FlatMenuProxyModel::start() { m_model->start(); } void FlatMenuProxyModel::stop() { m_model->stop(); } QModelIndex FlatMenuProxyModel::mapFromSource(const QModelIndex &index) const { if (!index.isValid()) { return QModelIndex(); } QModelIndex result = createIndex(rowOffsetOf(index, index.row()), 0); return result; } QModelIndex FlatMenuProxyModel::mapToSource(const QModelIndex &index) const { if (sourceModel() && m_indexCache.contains(index.row())) { QString key = m_indexCache.value(index.row()); QStringList sections = key.split('.', QString::SkipEmptyParts); QModelIndex sourceIndex = QModelIndex(); for(int i=0; i < sections.size(); i++) { sourceIndex = sourceModel()->index(sections.at(i).toInt(), 9, sourceIndex); } return sourceIndex; } else { return QModelIndex(); } } QModelIndex FlatMenuProxyModel::index(int row, int sectionRow, const QModelIndex &parent, const QString &key) const { for (int i = 0, count = 0; i < sourceModel()->rowCount(parent); i++) { QModelIndex sourceIndex = sourceModel()->index(i, 0, parent); int indexCount = recursiveRowCount(sourceIndex); if (count == sectionRow) { QString sectionKey = key + "." + QString::number(i); m_indexCache.insert(row, sectionKey); return createIndex(row, 0); } else if ((count + indexCount) >= sectionRow) { count++; return index(row, sectionRow - count, sourceIndex, key + "." + QString::number(i)); } count += indexCount + 1; } return QModelIndex(); } QModelIndex FlatMenuProxyModel::index(int row, int, const QModelIndex &) const { return index(row, row, QModelIndex(), ""); } QModelIndex FlatMenuProxyModel::parent(const QModelIndex &) const { return QModelIndex(); } int FlatMenuProxyModel::columnCount(const QModelIndex &) const { return 1; } int FlatMenuProxyModel::rowCount(const QModelIndex &) const { return m_rowCount; } int FlatMenuProxyModel::count() const { return rowCount(QModelIndex()); } void FlatMenuProxyModel::onModelAboutToBeReset() { beginResetModel(); } void FlatMenuProxyModel::onModelReset() { // initiliaze rowCount m_rowCount = 0; for (int i = 0, iMax = sourceModel()->rowCount(); i < iMax; i++) { QModelIndex index = sourceModel()->index(i, 0); m_rowCount += recursiveRowCount(index) + 1; } m_indexCache.clear(); endResetModel(); Q_EMIT countChanged(); } int FlatMenuProxyModel::recursiveRowCount(const QModelIndex &index) const { int size = sourceModel()->rowCount(index); for (int i=0, iMax=size; i < iMax; i++) { QModelIndex currentIndex = sourceModel()->index(i, 0, index); size += recursiveRowCount(currentIndex); } return size; } int FlatMenuProxyModel::rowOffsetOf(const QModelIndex &index, int row, bool inclusive) const { int offset = 0; QModelIndex parent = index.parent(); // Check row 0 offset while(parent.isValid()) { offset += 1; for (int i = 0; i < parent.row(); i++) { QModelIndex currentIndex = sourceModel()->index(i, 0, parent); offset += recursiveRowCount(currentIndex) + 1; } parent = parent.parent(); } // Check index.row() offset for(int i = 0; i < row; i++) { QModelIndex currentIndex = sourceModel()->index(i, 0, index.parent()); offset += recursiveRowCount(currentIndex) + 1; } if (inclusive) { // itself QModelIndex currentIndex = sourceModel()->index(row, 0, index.parent()); offset += recursiveRowCount(currentIndex); } return offset; } QVariant FlatMenuProxyModel::data(int row, int role) const { return QAbstractProxyModel::data(index(row, 0), role); }