如何超链接到 QAbstractItemModel 中的项目?
How to hyperlink to an item in a QAbstractItemModel?
使用的 Qt 版本:4.7.1 和 4.8
我将分层数据存储为从 QAbstractItemModel 派生的模型中的节点。我的应用程序 GUI 中有一个 QTreeView
来显示分层数据。 (分层数据对于这个问题可能不是必需的;我遇到的一般问题适用于任何模型和视图中的任何类型的数据。)
我的应用程序 GUI 中有一个显示超链接的文本框(一个 QPlainTextEdit
小部件,但这不是必需的)。当用户点击超链接时,我可以拦截它并获取超链接的 URL 。到目前为止,还不错。
当我拦截该超链接时,我将使 QTreeView
导航到特定节点,根据需要展开其父节点,以便用户可以看到它。
超链接的 URL 将采用让我知道正在请求节点的格式,并将包含有关该特定节点的标识信息。例如:
<a href="node://something">Click me to see node A</a>
所以,问题是:可以识别特定节点并可以编码为文本字符串的东西是什么?
我一直在阅读有关 QPersistentModelIndex
的内容。这听起来像是一个合理的开始。当我格式化超链接时,我肯定会知道特定节点的QModelIndex
,并可以从中构造一个QPersistentModelIndex
。但是我迷失了如何将其转换为字符串,然后将字符串转换回 QModelIndex
,我可以从中推断出特定的节点。
如有任何建议,我们将不胜感激。
您可以在您的模型中声明一个自定义 data role,并为您的每个项目设置此角色的唯一值。
//MyModel.h
class MyModel : public QAbstractItemModel
{
enum MyRoles {
UrlRole = Qt::UserRole
};
// (...)
}
//MyModel.cpp
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (role == UrlRole)
{
return "uniqueUrl"; //Up to you to decide what you return here
}
// (...)
}
然后在执行搜索时,只需使用模型的 match function 来匹配您的唯一字符串并从列表中获取第一个索引。
QModelIndex MyDialog::getIndexForUrl(QString myUrl)
{
QModelIndex index = QModelIndex();
QModelIndexList resultList = ui->treeView->model()->match(QModelIndex(),
MyModel::UrlRole, "uniqueUrl", 1, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (!resultList.empty())
{
index = resultList.first();
}
return index;
}
您可能需要根据您定义模型的方式调整标志和起始索引。
按照@Cendolt 的建议,使用QAbstractItemModel::match()
通过自定义数据角色在数据模型中搜索项目是一个绝妙的主意。我能够使用这个想法,而不必在我的自定义数据模型中覆盖 match()
。
不过,我提供给 QAbstractItemModel::match()
的参数略有不同。结合@Cendolt 示例的其余部分,以下内容适用于我的情况。
QAbstractItemModel * pModel = ...;
// Start searching from the root of the tree.
QModelIndex startIndex = pModel->index( 0, 0 );
QModelIndexList results = p->match(
startIndex,
MyModel::UrlRole,
"uniqueUrl",
1,
Qt::MatchRecursive );
有效的起始索引
为行和列指定一个以零开头的 QModelIndex
对于使搜索继续进行是必不可少的。当我使用默认构造的 QModelIndex
时,搜索从未调用我模型的 data()
方法。我相信这是因为默认构造的 QModelIndex
的行和列为 -1,这使其成为无效索引。在 QAbstractItemModel::match()
({Qt dir}\src\corelib\kernel\qabstractitemmodel.cpp) 的代码中,请注意,如果索引无效,它会跳过调用 data()
。
匹配标志
特别是对于分层数据,使用 Qt::MatchRecursive
标志是必不可少的。否则,搜索不会爬到子节点。
使用的 Qt 版本:4.7.1 和 4.8
我将分层数据存储为从 QAbstractItemModel 派生的模型中的节点。我的应用程序 GUI 中有一个 QTreeView
来显示分层数据。 (分层数据对于这个问题可能不是必需的;我遇到的一般问题适用于任何模型和视图中的任何类型的数据。)
我的应用程序 GUI 中有一个显示超链接的文本框(一个 QPlainTextEdit
小部件,但这不是必需的)。当用户点击超链接时,我可以拦截它并获取超链接的 URL 。到目前为止,还不错。
当我拦截该超链接时,我将使 QTreeView
导航到特定节点,根据需要展开其父节点,以便用户可以看到它。
超链接的 URL 将采用让我知道正在请求节点的格式,并将包含有关该特定节点的标识信息。例如:
<a href="node://something">Click me to see node A</a>
所以,问题是:可以识别特定节点并可以编码为文本字符串的东西是什么?
我一直在阅读有关 QPersistentModelIndex
的内容。这听起来像是一个合理的开始。当我格式化超链接时,我肯定会知道特定节点的QModelIndex
,并可以从中构造一个QPersistentModelIndex
。但是我迷失了如何将其转换为字符串,然后将字符串转换回 QModelIndex
,我可以从中推断出特定的节点。
如有任何建议,我们将不胜感激。
您可以在您的模型中声明一个自定义 data role,并为您的每个项目设置此角色的唯一值。
//MyModel.h
class MyModel : public QAbstractItemModel
{
enum MyRoles {
UrlRole = Qt::UserRole
};
// (...)
}
//MyModel.cpp
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (role == UrlRole)
{
return "uniqueUrl"; //Up to you to decide what you return here
}
// (...)
}
然后在执行搜索时,只需使用模型的 match function 来匹配您的唯一字符串并从列表中获取第一个索引。
QModelIndex MyDialog::getIndexForUrl(QString myUrl)
{
QModelIndex index = QModelIndex();
QModelIndexList resultList = ui->treeView->model()->match(QModelIndex(),
MyModel::UrlRole, "uniqueUrl", 1, Qt::MatchFixedString | Qt::MatchCaseSensitive);
if (!resultList.empty())
{
index = resultList.first();
}
return index;
}
您可能需要根据您定义模型的方式调整标志和起始索引。
按照@Cendolt 的建议,使用QAbstractItemModel::match()
通过自定义数据角色在数据模型中搜索项目是一个绝妙的主意。我能够使用这个想法,而不必在我的自定义数据模型中覆盖 match()
。
不过,我提供给 QAbstractItemModel::match()
的参数略有不同。结合@Cendolt 示例的其余部分,以下内容适用于我的情况。
QAbstractItemModel * pModel = ...;
// Start searching from the root of the tree.
QModelIndex startIndex = pModel->index( 0, 0 );
QModelIndexList results = p->match(
startIndex,
MyModel::UrlRole,
"uniqueUrl",
1,
Qt::MatchRecursive );
有效的起始索引
为行和列指定一个以零开头的 QModelIndex
对于使搜索继续进行是必不可少的。当我使用默认构造的 QModelIndex
时,搜索从未调用我模型的 data()
方法。我相信这是因为默认构造的 QModelIndex
的行和列为 -1,这使其成为无效索引。在 QAbstractItemModel::match()
({Qt dir}\src\corelib\kernel\qabstractitemmodel.cpp) 的代码中,请注意,如果索引无效,它会跳过调用 data()
。
匹配标志
特别是对于分层数据,使用 Qt::MatchRecursive
标志是必不可少的。否则,搜索不会爬到子节点。