summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);