diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -10,6 +10,7 @@ krearrangecolumnsproxymodel.cpp krecursivefilterproxymodel.cpp kselectionproxymodel.cpp + kcolumnheadersproxymodel.cpp ) ecm_qt_declare_logging_category(kitemmodels_SRCS HEADER kitemmodels_debug.h IDENTIFIER KITEMMODELS_LOG CATEGORY_NAME kf5.kitemmodels) @@ -51,6 +52,7 @@ KDescendantsProxyModel KModelIndexProxyMapper KSelectionProxyModel + KColumnHeadersProxyModel REQUIRED_HEADERS KItemModels_HEADERS ) @@ -75,6 +77,7 @@ kdescendantsproxymodel.h kmodelindexproxymapper.h kselectionproxymodel.h + kcolumnheadersproxymodel.h ) endif() diff --git a/src/core/kcolumnheadersproxymodel.h b/src/core/kcolumnheadersproxymodel.h new file mode 100644 --- /dev/null +++ b/src/core/kcolumnheadersproxymodel.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2019 Arjen Hiemstra + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef KCOLUMNHEADERSMODEL_H +#define KCOLUMNHEADERSMODEL_H + +#include "kitemmodels_export.h" + +#include + +/** + * A model that converts a model's headers into a list model. + * + * This model will expose the source model's headers as a simple list. This is + * mostly useful as a helper for QML applications that want to display a model's + * headers. + * + * @since 5.65 + */ +class KITEMMODELS_EXPORT KColumnHeadersProxyModel : public QAbstractProxyModel +{ + Q_OBJECT +public: + explicit KColumnHeadersProxyModel(QObject *parent = nullptr); + ~KColumnHeadersProxyModel() override; + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex{}) const override; + QModelIndex parent(const QModelIndex &child) const override; + int rowCount(const QModelIndex &parent = QModelIndex{}) const override; + int columnCount(const QModelIndex &parent = QModelIndex{}) const override; + + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; + + QVariant data(const QModelIndex &index, int role) const override; +}; + +#endif diff --git a/src/core/kcolumnheadersproxymodel.cpp b/src/core/kcolumnheadersproxymodel.cpp new file mode 100644 --- /dev/null +++ b/src/core/kcolumnheadersproxymodel.cpp @@ -0,0 +1,85 @@ +/* + Copyright (c) 2019 Arjen Hiemstra + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "kcolumnheadersproxymodel.h" + +KColumnHeadersProxyModel::KColumnHeadersProxyModel(QObject *parent) + : QAbstractProxyModel(parent) +{ +} + +KColumnHeadersProxyModel::~KColumnHeadersProxyModel() +{ +} + +QModelIndex KColumnHeadersProxyModel::index(int row, int column, const QModelIndex& parent) const +{ + if (!sourceModel() || parent.isValid()) { + return QModelIndex{}; + } + + if (column != 0 || row < 0 || row > rowCount() - 1) { + return QModelIndex{}; + } + + return createIndex(row, column); +} + +int KColumnHeadersProxyModel::rowCount(const QModelIndex& parent) const +{ + if (!sourceModel() || parent.isValid()) { + return 0; + } + + return sourceModel()->columnCount(); +} + +int KColumnHeadersProxyModel::columnCount(const QModelIndex& parent) const +{ + if (!sourceModel() || parent.isValid()) { + return 0; + } + + return 1; +} + +QModelIndex KColumnHeadersProxyModel::parent(const QModelIndex& child) const +{ + Q_UNUSED(child); + return QModelIndex{}; +} + +QModelIndex KColumnHeadersProxyModel::mapFromSource(const QModelIndex& sourceIndex) const +{ + return index(sourceIndex.column(), 0); +} + +QModelIndex KColumnHeadersProxyModel::mapToSource(const QModelIndex& proxyIndex) const +{ + return sourceModel()->index(0, proxyIndex.column()); +} + +QVariant KColumnHeadersProxyModel::data(const QModelIndex& index, int role) const +{ + if (!sourceModel() || !index.isValid()) { + return QVariant{}; + } + + return sourceModel()->headerData(index.row(), Qt::Horizontal, role); +} diff --git a/src/qml/plugin.cpp b/src/qml/plugin.cpp --- a/src/qml/plugin.cpp +++ b/src/qml/plugin.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "kconcatenaterowsproxymodel_qml.h" void Plugin::initializeEngine(QQmlEngine *engine, const char *uri) @@ -34,6 +35,5 @@ qmlRegisterType(); qmlRegisterExtendedType(uri, 1, 0, "KConcatenateRowsProxyModel"); qmlRegisterType(uri, 1, 0, "KDescendantsProxyModel"); + qmlRegisterType(uri, 1, 0, "KColumnHeadersProxyModel"); } - - diff --git a/tests/qml/columnheaders.qml b/tests/qml/columnheaders.qml new file mode 100644 --- /dev/null +++ b/tests/qml/columnheaders.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 +import org.kde.kitemmodels 1.0 + +// This test is somewhat lame in that it should only display a single "1". +// ListModel only has one column and no way of adding more. And there is not +// really another model that is simple to create from QML that does have columns +// and column headers. + +ListView { + model: KColumnHeadersProxyModel { + sourceModel: ListModel { + ListElement { display: "test1" } + ListElement { display: "test2" } + } + } + + delegate: Text { + text: model.display + } +} +