在QTableView / QSortFilterProxy中恢复原始订单

时间:2013-09-05 13:30:30

标签: c++ qt

我在视图和模型(QTableView)之间有一个QSortFilterProxyModel QStandardItemModel。问题是当我调用sort()时,我无法恢复表中行的原始顺序。我试图通过在飞行中将模型代理更改为QIdentityProxy但无济于事,因为唯一的变化是行重新编号但订单保持排序。

是否可能以某种方式“取消”数据?我认为,在这种情况下,代码是不必要的,但如果被问到则会发布。

我在Win x64上使用Qt5

P.S。:同样的问题在2009年发布here,但从未得到回答。

5 个答案:

答案 0 :(得分:3)

恢复初始未排序状态(已测试)

    sortModel->setSortRole(Qt::InitialSortOrderRole);
    sortModel->invalidate();

QSortFilterProxyModel::​setSortRole(int role)

答案 1 :(得分:2)

我的理解是你需要将排序恢复到默认状态?如果您在重置排序时以其返回默认值的方式覆盖QSortFilterProxyModel :: lessThan()函数,即:

return QSortFilterProxyModel::lessThan(left, right);

,并在排序“启用”时自定义排序结果?我想您还需要使用QAbstractItemModel :: reset()将代理模型重置为其原始状态。但是,它将重新填充整个模型数据,您将丢失选择信息。

答案 2 :(得分:2)

重点是手动排序按列-1(还原)和正常列号排序,并以某种方式拦截QHeaderViewQSortFilterProxyModel之间的通信。

所以,利用@ vahancho的回答中的一些见解,我设法实现了这样的排序:

class ProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
public:
    ProxyModel(QObject* parent = 0);

signals:
    void askOrder(int column, Qt::SortOrder order);

public slots:
    //! override of automatically called function
    void sort(int column, Qt::SortOrder order) 
    { 
        emit askOrder(column, order); 
    }

    //! real sorting happens here
    void doSort(int column, Qt::SortOrder order) 
    { 
        QSortFilterProxyModel::sort(column, order); 
    }
};

在父母方面我做了正确的连接并检查:

ResultsTable::ResultsTable(QWidget *parent) : QTableView(parent)
{
    /*...*/
    p_Header = new QHeaderView(this);
    p_Sort = new ProxyModel(this);
    connect(this, &ResultsTable::doSort, p_Sort, &ProxyModel::doSort);
    connect(p_Sort, &ProxyModel::askOrder, this, &ResultsTable::setSorting);
    /*...*/
    setSortingEnabled(true);
}

void ResultsTable::setSorting(int column, Qt::SortOrder order)
{
    if (p_Header->sortIndicatorOrder() == Qt::AscendingOrder && p_Header->isSortIndicatorShown() && m_PreviousSort == column)
    {
        p_Header->setSortIndicator(column, Qt::DescendingOrder);
        p_Header->setSortIndicatorShown(false);
        column = -1;
    }
    else
    {
        p_Header->setSortIndicatorShown(true);
    }
    m_PreviousSort = column;
    emit doSort(column, order);
}

这样我可以在QTableViewsortingEnabled时使用由true完成的自动排序处理。我已经尝试研究当点击表头以引导排序时Qt内部发生了什么,但是失败了,所以停止了这个解决方案。

我仍然不确定这种方式QTableView负责设置正确的排序指示是否正确,而不是QHeaderView本身(因为我认为此功能属于标题)。< / p>

答案 3 :(得分:0)

我喜欢使用左上角按钮来恢复顺序(即,按该按钮作为标题的行号排序)。这适用于pyqt 5.9中的标准类:

def __init__(self):
    #...
    tb = self.tableView # has sorting enabled and SortIndicator shown
    proxy = QSortFilterProxyModel(self)
    proxy.setSourceModel(self.model)
    tb.setModel(proxy)
    btn = tb.findChild(QAbstractButton)
    if btn:
        btn.disconnect()
        btn.clicked.connect(self.disableSorting)
    tb.horizontalHeader().setSortIndicator(-1, 0)

def disableSorting(self):
    self.tableView.model().sort(-1)
    self.tableView.horizontalHeader().setSortIndicator(-1, 0)

答案 4 :(得分:0)

这对我来说最有效:

QSortFilterProxyModel *proxyModel = myTableView->model ();
proxyModel->sort (-1);

请注意,这不会更新TableView的标题指示符,所以在调用上面的代码之前,我也在调用:

myTableView->horizontalHeader ()->setSortIndicator (0, Qt::DescendingOrder);

我真的不喜欢它,但我还没有找到使用TableView或Horizo​​ntalHeader来重置QSortFilterProxyModel排序的方法。

这是完整的代码:

// Block QHeaderView signals so sorting doesn't happen twice
myTableView->horizontalHeader ()->blockSignals (true);

// Update the sort indicator to be the same as it was when the TableView was created
myTableView->horizontalHeader ()->setSortIndicator (0, Qt::DescendingOrder);

// Reset sorting
QSortFilterProxyModel *proxyModel = myTableView->model ();
proxyModel->sort (-1);

// Unblock QHeaderView signals
myTableView->horizontalHeader ()->blockSignals (false);

注意:我暂时阻止了水平标头信号,以防止QSortFilterProxyModel排序执行两次。

相关问题