summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>2015-07-21 17:07:14 +0200
committerMitch Curtis <mitch.curtis@theqtcompany.com>2015-07-27 10:39:44 +0000
commit09d9ce27ab9ac29aaa36c6d54fe89064dfcde69f (patch)
treefb03cccd2afc67155362d7d6980a89b4633efff2
parentdd9f2665b1f84f0ba8ed21f5c47b532b2dc4db87 (diff)
downloadqtquickcontrols-09d9ce27ab9ac29aaa36c6d54fe89064dfcde69f.tar.gz
TreeView: Add rootIndex property
Its purpose is the same as QAbstractItemView::rootIndex and allows to display only the part of the model data that is descendant of this index. The filesystembrowser example has been updated to only show files reachable from the user's home directory. [ChangeLog][TreeView] Added rootIndex property Change-Id: Ib8d9af4ce9d1f341ab509de3cc991773830ba9f4 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
-rw-r--r--examples/quick/controls/filesystembrowser/main.cpp1
-rw-r--r--examples/quick/controls/filesystembrowser/main.qml6
-rw-r--r--src/controls/Private/qquicktreemodeladaptor.cpp52
-rw-r--r--src/controls/Private/qquicktreemodeladaptor_p.h6
-rw-r--r--src/controls/TreeView.qml1
-rw-r--r--src/controls/doc/src/qtquickcontrols-treeview.qdoc13
-rw-r--r--src/controls/plugin.cpp3
-rw-r--r--tests/auto/qquicktreemodeladaptor/tst_qquicktreemodeladaptor.cpp47
8 files changed, 107 insertions, 22 deletions
diff --git a/examples/quick/controls/filesystembrowser/main.cpp b/examples/quick/controls/filesystembrowser/main.cpp
index 176d334c..1322bc49 100644
--- a/examples/quick/controls/filesystembrowser/main.cpp
+++ b/examples/quick/controls/filesystembrowser/main.cpp
@@ -137,6 +137,7 @@ int main(int argc, char *argv[])
fsm->setRootPath(QDir::homePath());
fsm->setResolveSymlinks(true);
engine.rootContext()->setContextProperty("fileSystemModel", fsm);
+ engine.rootContext()->setContextProperty("rootPathIndex", fsm->index(fsm->rootPath()));
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
return app.exec();
diff --git a/examples/quick/controls/filesystembrowser/main.qml b/examples/quick/controls/filesystembrowser/main.qml
index abc3c20c..b85002d5 100644
--- a/examples/quick/controls/filesystembrowser/main.qml
+++ b/examples/quick/controls/filesystembrowser/main.qml
@@ -39,7 +39,7 @@
****************************************************************************/
import QtQuick 2.2
-import QtQuick.Controls 1.4
+import QtQuick.Controls 1.5
import QtQml.Models 2.2
ApplicationWindow {
@@ -90,6 +90,7 @@ ApplicationWindow {
anchors.fill: parent
anchors.margins: 2 * 12 + row.height
model: fileSystemModel
+ rootIndex: rootPathIndex
selection: sel
TableViewColumn {
@@ -103,12 +104,14 @@ ApplicationWindow {
role: "size"
resizable: true
horizontalAlignment : Text.AlignRight
+ width: 70
}
TableViewColumn {
title: "Permissions"
role: "displayableFilePermissions"
resizable: true
+ width: 100
}
TableViewColumn {
@@ -117,7 +120,6 @@ ApplicationWindow {
resizable: true
}
- onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index)
onActivated : Qt.openUrlExternally(fileSystemModel.data(index, 263))
}
}
diff --git a/src/controls/Private/qquicktreemodeladaptor.cpp b/src/controls/Private/qquicktreemodeladaptor.cpp
index dddcdd01..0fda5704 100644
--- a/src/controls/Private/qquicktreemodeladaptor.cpp
+++ b/src/controls/Private/qquicktreemodeladaptor.cpp
@@ -120,6 +120,29 @@ void QQuickTreeModelAdaptor::clearModelData()
endResetModel();
}
+const QModelIndex &QQuickTreeModelAdaptor::rootIndex() const
+{
+ return m_rootIndex;
+}
+
+void QQuickTreeModelAdaptor::setRootIndex(const QModelIndex &idx)
+{
+ if (m_rootIndex == idx)
+ return;
+
+ if (m_model)
+ clearModelData();
+ m_rootIndex = idx;
+ if (m_model)
+ showModelTopLevelItems();
+ emit rootIndexChanged();
+}
+
+void QQuickTreeModelAdaptor::resetRootIndex()
+{
+ setRootIndex(QModelIndex());
+}
+
QHash<int, QByteArray> QQuickTreeModelAdaptor::roleNames() const
{
if (!m_model)
@@ -180,7 +203,7 @@ bool QQuickTreeModelAdaptor::setData(const QModelIndex &index, const QVariant &v
int QQuickTreeModelAdaptor::itemIndex(const QModelIndex &index) const
{
// This is basically a plagiarism of QTreeViewPrivate::viewIndex()
- if (!index.isValid() || m_items.isEmpty())
+ if (!index.isValid() || index == m_rootIndex || m_items.isEmpty())
return -1;
const int totalCount = m_items.count();
@@ -226,7 +249,7 @@ bool QQuickTreeModelAdaptor::isVisible(const QModelIndex &index)
bool QQuickTreeModelAdaptor::childrenVisible(const QModelIndex &index)
{
- return (!index.isValid() && !m_items.isEmpty())
+ return (index == m_rootIndex && !m_items.isEmpty())
|| (m_expandedItems.contains(index) && isVisible(index));
}
@@ -302,21 +325,21 @@ void QQuickTreeModelAdaptor::showModelTopLevelItems(bool doInsertRows)
if (!m_model)
return;
- if (m_model->hasChildren(QModelIndex()) && m_model->canFetchMore(QModelIndex()))
- m_model->fetchMore(QModelIndex());
- const long topLevelRowCount = m_model->rowCount();
+ if (m_model->hasChildren(m_rootIndex) && m_model->canFetchMore(m_rootIndex))
+ m_model->fetchMore(m_rootIndex);
+ const long topLevelRowCount = m_model->rowCount(m_rootIndex);
if (topLevelRowCount == 0)
return;
- showModelChildItems(TreeItem(), 0, topLevelRowCount - 1, doInsertRows);
+ showModelChildItems(TreeItem(m_rootIndex), 0, topLevelRowCount - 1, doInsertRows);
}
void QQuickTreeModelAdaptor::showModelChildItems(const TreeItem &parentItem, int start, int end, bool doInsertRows, bool doExpandPendingRows)
{
const QModelIndex &parentIndex = parentItem.index;
- int rowIdx = parentIndex.isValid() ? itemIndex(parentIndex) + 1 : 0;
+ int rowIdx = parentIndex.isValid() && parentIndex != m_rootIndex ? itemIndex(parentIndex) + 1 : 0;
Q_ASSERT(rowIdx == 0 || parentItem.expanded);
- if (parentIndex.isValid() && (rowIdx == 0 || !parentItem.expanded))
+ if (parentIndex.isValid() && parentIndex != m_rootIndex && (rowIdx == 0 || !parentItem.expanded))
return;
if (m_model->rowCount(parentIndex) == 0) {
@@ -603,8 +626,11 @@ void QQuickTreeModelAdaptor::modelRowsInserted(const QModelIndex & parent, int s
ASSERT_CONSISTENCY();
return;
}
- } else if (parent.isValid()) {
+ } else if (parent == m_rootIndex) {
item = TreeItem(parent);
+ } else {
+ ASSERT_CONSISTENCY();
+ return;
}
showModelChildItems(item, start, end);
ASSERT_CONSISTENCY();
@@ -612,10 +638,8 @@ void QQuickTreeModelAdaptor::modelRowsInserted(const QModelIndex & parent, int s
void QQuickTreeModelAdaptor::modelRowsAboutToBeRemoved(const QModelIndex & parent, int start, int end)
{
- Q_UNUSED(start);
- Q_UNUSED(end);
ASSERT_CONSISTENCY();
- if (!parent.isValid() || childrenVisible(parent)) {
+ if (parent == m_rootIndex || childrenVisible(parent)) {
const QModelIndex &smi = m_model->index(start, 0, parent);
int startIndex = itemIndex(smi);
const QModelIndex &emi = m_model->index(end, 0, parent);
@@ -756,9 +780,9 @@ bool QQuickTreeModelAdaptor::testConsistency(bool dumpOnFail) const
}
return true;
}
- QModelIndex parent;
+ QModelIndex parent = m_rootIndex;
QStack<QModelIndex> ancestors;
- QModelIndex idx = m_model->index(0, 0);
+ QModelIndex idx = m_model->index(0, 0, parent);
for (int i = 0; i < m_items.count(); i++) {
bool isConsistent = true;
const TreeItem &item = m_items.at(i);
diff --git a/src/controls/Private/qquicktreemodeladaptor_p.h b/src/controls/Private/qquicktreemodeladaptor_p.h
index 2297c365..3eefbe77 100644
--- a/src/controls/Private/qquicktreemodeladaptor_p.h
+++ b/src/controls/Private/qquicktreemodeladaptor_p.h
@@ -61,6 +61,7 @@ class QQuickTreeModelAdaptor : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QModelIndex rootIndex READ rootIndex WRITE setRootIndex RESET resetRootIndex NOTIFY rootIndexChanged)
struct TreeItem;
@@ -68,6 +69,9 @@ public:
explicit QQuickTreeModelAdaptor(QObject *parent = 0);
QAbstractItemModel *model() const;
+ const QModelIndex &rootIndex() const;
+ void setRootIndex(const QModelIndex &idx);
+ void resetRootIndex();
enum {
DepthRole = Qt::UserRole - 4,
@@ -110,6 +114,7 @@ public:
signals:
void modelChanged(QAbstractItemModel *model);
+ void rootIndexChanged();
void expanded(const QModelIndex &index);
void collapsed(const QModelIndex &index);
@@ -149,6 +154,7 @@ private:
};
QPointer<QAbstractItemModel> m_model;
+ QPersistentModelIndex m_rootIndex;
QList<TreeItem> m_items;
QSet<QPersistentModelIndex> m_expandedItems;
QList<TreeItem *> m_itemsToExpand;
diff --git a/src/controls/TreeView.qml b/src/controls/TreeView.qml
index c97930f3..637c46c3 100644
--- a/src/controls/TreeView.qml
+++ b/src/controls/TreeView.qml
@@ -44,6 +44,7 @@ BasicTableView {
id: root
property var model: null
+ property alias rootIndex: modelAdaptor.rootIndex
readonly property var currentIndex: modelAdaptor.mapRowToModelIndex(__currentRow)
property ItemSelectionModel selection: null
diff --git a/src/controls/doc/src/qtquickcontrols-treeview.qdoc b/src/controls/doc/src/qtquickcontrols-treeview.qdoc
index fb186059..a9d41b70 100644
--- a/src/controls/doc/src/qtquickcontrols-treeview.qdoc
+++ b/src/controls/doc/src/qtquickcontrols-treeview.qdoc
@@ -142,6 +142,19 @@
*/
/*!
+ \qmlproperty QModelIndex TreeView::rootIndex
+ The model index of the root item in the tree view. The root item is the
+ parent item to the view's top-level items. Only items descending from the
+ root item will be visible in the view.
+
+ Its default value is an invalid QModelIndex, which means the whole
+ model data is shown by the tree view (assigning \c undefined to this
+ proprety resets it to its default value.)
+
+ \since QtQuick.Controls 1.5
+*/
+
+/*!
\qmlproperty QModelIndex TreeView::currentIndex
The model index of the current row in the tree view.
*/
diff --git a/src/controls/plugin.cpp b/src/controls/plugin.cpp
index f20cada1..802dacb0 100644
--- a/src/controls/plugin.cpp
+++ b/src/controls/plugin.cpp
@@ -113,7 +113,8 @@ static const struct {
{ "TreeView", 1, 4 },
- { "TextArea", 1, 5 }
+ { "TextArea", 1, 5 },
+ { "TreeView", 1, 5 }
};
void QtQuickControlsPlugin::registerTypes(const char *uri)
diff --git a/tests/auto/qquicktreemodeladaptor/tst_qquicktreemodeladaptor.cpp b/tests/auto/qquicktreemodeladaptor/tst_qquicktreemodeladaptor.cpp
index b484665d..13a92ea7 100644
--- a/tests/auto/qquicktreemodeladaptor/tst_qquicktreemodeladaptor.cpp
+++ b/tests/auto/qquicktreemodeladaptor/tst_qquicktreemodeladaptor.cpp
@@ -57,6 +57,8 @@ private slots:
void modelDestroyed();
void modelReset();
+ void rootIndex();
+
void dataAccess();
void dataChange();
void groupedDataChange();
@@ -96,9 +98,10 @@ void tst_QQuickTreeModelAdaptor::cleanup()
void tst_QQuickTreeModelAdaptor::compareData(int row, QQuickTreeModelAdaptor &tma, const QModelIndex &modelIdx, TestModel &model, bool expanded)
{
const QModelIndex &tmaIdx = tma.index(row);
+ const int indexDepth = model.level(modelIdx) - model.level(tma.rootIndex()) - 1;
QCOMPARE(tma.mapToModel(tmaIdx), modelIdx);
QCOMPARE(tma.data(tmaIdx, Qt::DisplayRole).toString(), model.displayData(modelIdx));
- QCOMPARE(tma.data(tmaIdx, QQuickTreeModelAdaptor::DepthRole).toInt(), model.level(modelIdx));
+ QCOMPARE(tma.data(tmaIdx, QQuickTreeModelAdaptor::DepthRole).toInt(), indexDepth);
QCOMPARE(tma.data(tmaIdx, QQuickTreeModelAdaptor::ExpandedRole).toBool(), expanded);
QCOMPARE(tma.data(tmaIdx, QQuickTreeModelAdaptor::HasChildrenRole).toBool(), model.hasChildren(modelIdx));
}
@@ -117,7 +120,7 @@ void tst_QQuickTreeModelAdaptor::expandAndTest(const QModelIndex &idx, QQuickTre
const QModelIndex &tmaIdx = tma.index(tma.itemIndex(idx));
QCOMPARE(tma.data(tmaIdx, QQuickTreeModelAdaptor::ExpandedRole).toBool(), expandable);
- if (expandable) {
+ if (expandable && expectedRowCountDifference != 0) {
// Rows were added below the parent
QCOMPARE(tma.rowCount(), oldRowCount + expectedRowCountDifference);
QCOMPARE(rowsAboutToBeInsertedSpy.count(), rowsInsertedSpy.count());
@@ -160,7 +163,7 @@ void tst_QQuickTreeModelAdaptor::collapseAndTest(const QModelIndex &idx, QQuickT
if (tmaIdx.isValid())
QCOMPARE(tma.data(tmaIdx, QQuickTreeModelAdaptor::ExpandedRole).toBool(), false);
- if (expandable) {
+ if (expandable && expectedRowCountDifference != 0) {
// Rows were removed below the parent
QCOMPARE(tma.rowCount(), oldRowCount - expectedRowCountDifference);
QCOMPARE(rowsAboutToBeRemovedSpy.count(), 1);
@@ -188,9 +191,9 @@ void tst_QQuickTreeModelAdaptor::collapseAndTest(const QModelIndex &idx, QQuickT
void tst_QQuickTreeModelAdaptor::compareModels(QQuickTreeModelAdaptor &tma, TestModel &model)
{
- QModelIndex parent;
+ QModelIndex parent = tma.rootIndex();
QStack<QModelIndex> parents;
- QModelIndex idx = model.index(0, 0);
+ QModelIndex idx = model.index(0, 0, parent);
int modelVisibleRows = model.rowCount(parent);
for (int i = 0; i < tma.rowCount(); i++) {
bool expanded = tma.isExpanded(i);
@@ -283,6 +286,40 @@ void tst_QQuickTreeModelAdaptor::modelReset()
compareModels(tma, model);
}
+void tst_QQuickTreeModelAdaptor::rootIndex()
+{
+ TestModel model(5, 1);
+
+ QQuickTreeModelAdaptor tma;
+ tma.setModel(&model);
+
+ QVERIFY(!tma.rootIndex().isValid());
+ compareModels(tma, model);
+
+ QSignalSpy rootIndexSpy(&tma, SIGNAL(rootIndexChanged()));
+ QModelIndex rootIndex = model.index(0, 0);
+ tma.setRootIndex(rootIndex);
+ QCOMPARE(tma.rootIndex(), rootIndex);
+ QCOMPARE(rootIndexSpy.count(), 1);
+ compareModels(tma, model);
+
+ rootIndexSpy.clear();
+ rootIndex = model.index(2, 2, tma.rootIndex());
+ tma.setRootIndex(rootIndex);
+ QCOMPARE(tma.rootIndex(), rootIndex);
+ QCOMPARE(rootIndexSpy.count(), 1);
+ compareModels(tma, model);
+
+ // Expand 1st visible item, business as usual
+ expandAndTest(model.index(0, 0, rootIndex), tma, true /*expandable*/, 5);
+ // Expand non root item descendant item, nothing should happen
+ expandAndTest(model.index(0, 0), tma, true /*expandable*/, 0);
+ // Collapse 1st visible item, business as usual
+ collapseAndTest(model.index(0, 0, rootIndex), tma, true /*expandable*/, 5);
+ // Collapse non root item descendant item, nothing should happen
+ collapseAndTest(model.index(0, 0), tma, true /*expandable*/, 0);
+}
+
void tst_QQuickTreeModelAdaptor::dataAccess()
{
TestModel model(5, 1);