【问题标题】:Strange behavior of QTableView with text containing slashes带有斜杠的 QTableView 的奇怪行为
【发布时间】:2022-08-11 22:24:29
【问题描述】:

我们最近将一个项目从 Qt 4.8 移植到 Qt 5.15(由于依赖关系,Qt 6 还不是我们的选择)。

我们发现当一个项目的文本包含斜杠时,我们所有的 QTableView 都会表现得很奇怪。 这是一个演示 2 个问题的小程序:

#include <QTableWidget>
#include <QAbstractItemModel>
#include <QApplication>
#include <QDebug>


int main(int argc, char** argv)
{
    QApplication app(argc, argv);

    QTableWidget tbl;
    tbl.setTextElideMode(Qt::ElideLeft);
    tbl.setColumnCount(2);
    tbl.setRowCount(argc-1);
    for (int i = 1; i < argc; ++i)
    {
        tbl.setItem( i-1, 0, new QTableWidgetItem(QString::number(i)) );
        tbl.setItem( i-1, 1, new QTableWidgetItem(argv[i]) );
    }
    tbl.show();
    
    auto* pModel = tbl.model();
    QString qstrMatch = \"*single*file*\";
    QModelIndexList lst = pModel->match(pModel->index(0,1), Qt::DisplayRole, qstrMatch, -1, Qt::MatchWildcard);
    qDebug() << lst.size() << \"results\";
    for (const QModelIndex& idx : lst)
    {
        qDebug() << argv[1+idx.row()];
    }

    return app.exec();
}

假设我们使用以下 4 个字符串运行该程序:

/path/to/design/patterns/singleton_file.txt
/path/to/design/patterns/observer_file.txt
just_single_name_file_no_path.txt
drill a single 1/4 inch hole then file here

1) 文本省略

在 Qt 4 中,Qt::ElideLeft 在所有情况下都受到尊重:

但在 Qt 5 中,每当文本包含斜杠时似乎都会出现问题:

一位同事注意到一个表仍在按预期工作,并发现它的不同之处在于使用了自定义委托。 果然,只需在其他表上执行tbl.setItemDelegate(new QItemDelegate) 也可以解决他们的问题。 但这似乎没有任何意义。

2)文本匹配

在 Qt 4 中,对 match 函数的调用确实会返回 3 个结果,如预期的那样。 在 Qt 5 中,它只返回 1 个结果 - 对于不包含斜杠的字符串。

不过,通过使用 QRegExpWildcard 语法来使用我们自己的循环实现搜索可以按预期工作。


https://doc.qt.io/qt-5.15/sourcebreaks.html 没有提供任何可能发生变化的指针。

    标签: c++ qt text


    【解决方案1】:

    在深入研究了 Qt 5 的源代码之后,我们能够找到这些问题背后的原因和解决方案。

    这两个问题无关。

    1) 文本省略

    在研究了一段时间的 Qt 源代码后,我偶然发现了QTableView::setWordWrap 的这个文档评论:

    请注意,即使启用了换行,单元格也不会扩展以适合所有文本。省略号将根据当前的 textElideMode 插入。

    自动换行是默认开启的,它的效果只有在你手动调整行大小时才会变得清晰:

    所以“...”不是用于“水平”文本宽度省略,而是用于“垂直”换行截断。 解决方案是在QTableView 上简单地使用:setWordWrap(false)

    使用QItemDelegate 的原因似乎是它的实现做了简单的省略自动换行,而QStyledItemDelegate(默认)首先换行然后仅省略包含无法换行的很长单词的行。 (目前尚不清楚 Qt 4 中哪一部分做了不同的处理:可能斜线不被视为换行的有效字边界。)

    2)文本匹配

    根本区别在于QAbstractItemModel::match 函数:之前使用QRegExpWildcard 语法与现在使用QRegularExpression::wildcardToRegularExpression。 正如后一个函数的文档所述:

    转换的目标是文件路径通配,这尤其意味着路径分隔符接受特殊处理。

    这意味着每个项目的文本都被视为文件路径,并且 (a) 整个路径必须匹配,并且 (b) * 匹配不能跨越斜线(它转换为类似于 [^/]* 而不仅仅是 @ 987654334@)。 该函数的 Qt 6 版本在地址 (a) 中引入了 UnanchoredWildcardConversion 标志,但在 (b) 中没有,并且无论如何都无法从 QAbstractItemModel::match 中控制它。 所以唯一的解决方案(如果我们选择使用QAbstractItemModel::match而不是滚动我们自己的循环)似乎是编写我们自己的wildcardToRegularExpression实现,它不假设通配符用于文件路径,因此不特别对待路径分隔符。

    【讨论】:

      猜你喜欢
      • 2019-04-09
      • 2015-03-24
      • 1970-01-01
      • 1970-01-01
      • 2017-01-27
      • 2013-11-02
      • 2020-11-19
      • 1970-01-01
      • 2011-08-30
      相关资源
      最近更新 更多