【Qt筆記】QSortFilterProxyModel

從本章開始,咱們將逐步瞭解有關自定義模型的相關內容。儘管前面咱們曾經介紹過 Qt 提供的幾個內置模型:QStringListModelQFileSystemModel,但對於變幻無窮的需求而言,這些顯然是遠遠不夠的。因而,Qt 也容許咱們對模型進行自定義。正則表達式

在正式開始介紹自定義模形以前,咱們先來了解一個新的類:QSortFilterProxyModel。之因此將這個類放在這裏,是由於在必定程序上,咱們可使用QSortFilterProxyModel得到一些可能必須自定義才能達到的效果。QSortFilterProxyModel並不能單獨使用。顧名思義,它是一個「代理」,其真正的數據須要另外的一個模型提供。它的做用是對數據進行排序和過濾。排序很好理解,而過濾,則是按照輸入的內容對數據及進行篩選,很像 Excel 裏面的過濾器。不過 Qt 提供的過濾功能是基於正則表達式的,功能很強大。shell

 

下面咱們根據代碼來了解下QSortFilterProxyModel的使用:express

#ifndef SORTVIEW_H
#define SORTVIEW_H

#include <QWidget>
#include <QListView>
#include <QStringListModel>
#include <QSortFilterProxyModel>
#include <QComboBox>

class SortView : public QWidget
{
    Q_OBJECT
public:
    SortView();

private:
    QListView *view;
    QStringListModel *model;
    QSortFilterProxyModel *modelProxy;
    QComboBox *syntaxBox;

private slots:
    void filterChanged(const QString &text);
};

#endif // SORTVIEW_H

頭文件中,咱們聲明瞭一個類SortView,繼承自QWidget。它有四個成員變量以及一個私有槽函數。函數

#include "sortview.h"

#include <QLineEdit>
#include <QLabel>
#include <QHBoxLayout>

SortView::SortView()
{
    model = new QStringListModel(QColor::colorNames(), this);

    modelProxy = new QSortFilterProxyModel(this);
    modelProxy->setSourceModel(model);
    modelProxy->setFilterKeyColumn(0);

    view = new QListView(this);
    view->setModel(modelProxy);

    QLineEdit *filterInput = new QLineEdit;
    QLabel *filterLabel = new QLabel(tr("Filter"));
    QHBoxLayout *filterLayout = new QHBoxLayout;
    filterLayout->addWidget(filterLabel);
    filterLayout->addWidget(filterInput);

    syntaxBox = new QComboBox;
    syntaxBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    syntaxBox->addItem(tr("Regular expression"), QRegExp::RegExp);
    syntaxBox->addItem(tr("Wildcard"), QRegExp::Wildcard);
    syntaxBox->addItem(tr("Fixed string"), QRegExp::FixedString);
    QLabel *syntaxLabel = new QLabel(tr("Syntax"));
    QHBoxLayout *syntaxLayout = new QHBoxLayout;
    syntaxLayout->addWidget(syntaxLabel);
    syntaxLayout->addWidget(syntaxBox);

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(view);
    layout->addLayout(filterLayout);
    layout->addLayout(syntaxLayout);

    connect(filterInput, SIGNAL(textChanged(QString)),
            this, SLOT(filterChanged(QString)));
}

在構造函數中,咱們首先建立一個QStringListModel對象,其內容是 Qt 預約義的全部顏色的名字(利用QColor::colorNames()獲取)。而後是QSortFilterProxyModel對象,咱們將其原模型設置爲剛剛建立的 model,也就是要爲這個 model 進行代理;而後將FilterKeyColumn設置爲 0,也就是僅僅對第一列進行過濾。咱們使用一個QStringListModel包裝這個數據,這和前面的內容沒有什麼區別。而後建立一個QSortFilterProxyModel對象,使用它的setSourceModel()函數將前面定義的QStringListModel傳進去,也就是咱們須要對這個 model 進行代理。最後重要的一點是,QListView的數據源必須設置爲QSortFilterProxyModel,而不是最開始的 model 對象。工具

做爲過濾選項,syntaxBox 添加了三個數據項:this

syntaxBox->addItem(tr("Regular expression"), QRegExp::RegExp);
syntaxBox->addItem(tr("Wildcard"), QRegExp::Wildcard);
syntaxBox->addItem(tr("Fixed string"), QRegExp::FixedString);

這正是正則表達式的幾種類型。正則表達式本身有一套相對通用的語法,可是對於不一樣的語言環境(例如 Java、C# 和 Python),其具體定義可能會略有差異。這裏咱們使用的是 Qt 本身的正則表達式處理工具(C++ 自己並無解析正則表達式的機制,雖然 boost 提供了一套)。第一個QregExp::RegExp提供了最通常的正則表達式語法,但這個語法不支持貪婪限定符。這也是 Qt 默認的規則;若是須要使用貪婪限定符,須要使用QRegExp::RegExp2。儘管在 Qt4 的文檔中聲明,QRegExp::RegExp2將會做爲 Qt5 的默認規則,但其實並非這樣。第二個咱們提供的是 Unix shell 常見的一種規則,使用通配符處理。第三個即固定表達式,也就是說基本上不使用正則表達式。代理

接下來咱們看看 filterChanged() 函數的實現:code

void SortView::filterChanged(const QString &text)
{
    QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(
                syntaxBox->itemData(syntaxBox->currentIndex()).toInt());
    QRegExp regExp(text, Qt::CaseInsensitive, syntax);
    modelProxy->setFilterRegExp(regExp);
}

在這段代碼中,首先使用QComboBox的選擇值建立一個QRegExp::PatternSyntax對象;而後利用這個語法規則構造一個正則表達式,注意咱們在QLineEdit裏面輸入的內容是經過參數傳遞進來的,而後設置數據模型代理的過濾表達式。下面能夠運行一下看看結果:對象

上圖中,咱們輸入的是 gr[ae]y 做爲正則表達式。這是說,咱們但願獲取這樣一個顏色的名字:它的名字中有這樣的四個字母,第一個字母是 g,第二個字母是 r,第三個字母要麼是 a,要麼是 e,第四個字母是 y。若是找到符合條件的名字,就要把它過濾出來,顯示到列表中,不符合條件的所有不顯示。咱們的程序正是這樣的結果。若是你對這個正則表達式不熟悉,請自行查閱有關正則表達式的內容。排序

相關文章
相關標籤/搜索