Qt Creator 插件开发(16):向查找对话框添加过滤器

Qt Creator 的查找对话框允许用户使用文本或者正则表达式进行搜索。点击“编辑-查找/替换-高级查找”即可打开查找对话框。

打开 Qt Creator 查找对话框

查找对话框:

Qt Creator 查找对话框

在查找对话框中,“范围”和“文件模式”两项都是可以扩展的。也是就说,我们可以利用插件,向范围下拉框添加更多项目,每次都可以依据选择的下拉项不同,读取不同的配置文件。在 Qt Creator 中,范围下拉框中的每一项都叫做“查找过滤器(find filter)”。

Find::IFindFilter

Qt Creator 的 find 插件暴露出的接口是Find::IFindFilter,该接口在 src/plugins/find/ifindfilter.h 中声明:

#ifndef IFINDFILTER_H
#define IFINDFILTER_H

#include "find_global.h"
#include "textfindconstants.h"

QT_BEGIN_NAMESPACE
class QWidget;
class QSettings;
class QKeySequence;
QT_END_NAMESPACE

namespace Find {

class FIND_EXPORT IFindFilter : public QObject
{
    Q_OBJECT
public:

    virtual ~IFindFilter() {}

    virtual QString id() const = 0;
    virtual QString displayName() const = 0;
    ///
    virtual bool isEnabled() const = 0;
    virtual bool canCancel() const = 0;
    virtual void cancel() = 0;
    virtual QKeySequence defaultShortcut() const;
    virtual bool isReplaceSupported() const { return false; }
    virtual FindFlags supportedFindFlags() const;

    virtual void findAll(const QString &txt, Find::FindFlags findFlags) = 0;
    virtual void replaceAll(const QString &txt, Find::FindFlags findFlags)
    { Q_UNUSED(txt) Q_UNUSED(findFlags) }

    virtual QWidget *createConfigWidget() { return 0; }
    virtual void writeSettings(QSettings *settings) { Q_UNUSED(settings) }
    virtual void readSettings(QSettings *settings) { Q_UNUSED(settings) }

signals:
    void changed();
};

} // namespace Find

#endif // IFINDFILTER_H

通过实现IFindFilter接口,然后将其实例添加到对象池,我们就可以注册一个新的文件过滤器,这意味着我们将会在前面提到的查找对话框的“范围”下拉框中找到新的一项。

自定义过滤器

假设我们需要一个自定义过滤器,用于在已打开工程中查找一个给定的头文件。那么,我们可以根据下面的几个步骤来理解如何编写这个查找过滤器。

1. 声明HeaderFilter

首先,我们需要声明一个实现了Find::IFindFilter接口的类,也就是HeaderFilter。这个类定义如下:

#ifndef HEADERFILTER_H
#define HEADERFILTER_H

#include 

class HeaderFilterData;

class HeaderFilter : public Find::IFindFilter
{
    Q_OBJECT
public:
    HeaderFilter();
    ~HeaderFilter();
    QString id() const;
    QString displayName() const;
    bool isEnabled() const;
    bool canCancel() const;
    void cancel();
    QKeySequence defaultShortcut() const;
    void findAll(const QString &txt, Find::FindFlags findFlags);
    QWidget *createConfigWidget();
private:
    HeaderFilterData *d;
};

#endif // HEADERFILTER_H

2. 实现 HeaderFilter 类

构造函数和析构函数都是空白的。我们会在后面详细了解过IFindFilter的工作过程之后再来填入更多的代码。

struct HeaderFilterData
{
};

HeaderFilter::HeaderFilter()
{
    d = new HeaderFilterData;
}

HeaderFilter::~HeaderFilter()
{
    delete d;
}

id()函数用于该 filter 的唯一标示符:

QString HeaderFilter::id() const
{
    return "HeaderFilter";
}

displayName()函数用于在范围下拉框中显示:

QString HeaderFilter::displayName() const
{
    return tr("Header Filter");
}

isEnabled()函数返回 bool 值,表示该过滤器是否可用。在这个例子中,我们希望在 Qt Creator 加载了项目之后,该过滤器可用,否则不可用。为了更进一步了解该函数的作用,我们必须了解ProjectExplorer命名空间。现在,我们简单的将其返回值设置为 true,等到学习过 ProjectExplorer 命名空间之后再对此函数作进一步完善。

bool HeaderFilter::isEnabled() const
{
    return true;
}

canCancel()cancel()函数用于表示该过滤器能够被取消。这里我们也是用最简单的代码:

bool HeaderFilter::canCancel() const
{
    return true;
}

void HeaderFilter::cancel()
{
    // Do nothing
}

defaultShortcut()函数返回与此过滤器相关的快捷键。用户按下该快捷键之后,查找对话框将自动打开,并且该过滤器被选中。在本例中,我们返回一个非法快捷键:

QKeySequence HeaderFilter::defaultShortcut() const
{
    return QKeySequence();
}

createConfigWidget()函数返回一个用于配置的组件。这个组件将显示在查找对话框的最下方(注意本文开始的查找对话框图片中,最下方的“文件模式”的位置)。在本例中,我们不需要对 header filter 作任何配置,因此使用一个 label 显示即可:

QWidget *HeaderFilter::createConfigWidget()
{
    return (new QLabel("This is a header filter"));
}

findAll()函数用于实现真实的“查找”操作。我们需要了解ProjectExplorerTextEditorFindCore::Utils这几个命名空间之后才能编写实际代码。所以现在,我们的findAll()函数还是空白的:

void HeaderFilter::findAll(const QString &text, Find::FindFlags findFlags)
{
    // Do nothing
}

3. 实现HeaderFilterPlugin代码

HeaderFilterPlugin代码同前面一样,我们只需修改 initialize()函数:

bool HeaderFilterPlugin::initialize(const QStringList& args, QString *errMsg)
{
    Q_UNUSED(args);
    Q_UNUSED(errMsg);

    addAutoReleasedObject(new HeaderFilter);

    return true;
}

4. 测试

将我们的代码编译之后,重启 Qt Creator。我们之前仅仅使用了 coreplugin 这个插件,而现在,我们需要使用 find。这需要修改 pro 文件:

QTC_SOURCE      = E:/codelibs/QtCreator/qt-creator-2.2.1-src
QTC_BUILD       = E:/codelibs/QtCreator/build/
TEMPLATE        = lib
TARGET          = HeaderFilterPlugin
IDE_SOURCE_TREE = $$QTC_SOURCE
IDE_BUILD_TREE  = $$QTC_BUILD
PROVIDER        = GalaxyWorld
DESTDIR         = $$QTC_BUILD/lib/qtcreator/plugins/GalaxyWorld
LIBS           += -L$$QTC_BUILD/lib/qtcreator/plugins/Nokia
include($$QTC_SOURCE/src/qtcreatorplugin.pri)
include($$QTC_SOURCE/src/plugins/coreplugin/coreplugin.pri)
include($$QTC_SOURCE/src/plugins/find/find.pri)
HEADERS         = HeaderFilterPlugin.h HeaderFilter.h
SOURCES         = HeaderFilterPlugin.cpp HeaderFilter.cpp
OTHER_FILES     = HeaderFilterPlugin.pluginspec

注意其中添加了 find.pri 一行。

现在,我们可以在查找对话框中看到新增加的 Header Filter 一项。注意在范围下拉框中的显示以及对话框下方的配置组件。

HeaderFilter 测试

现在,由于我们的findAll()函数没有实现,我们仅仅为对话框提供了一个没有“查找”功能的界面。在后面的章节中,我们将继续完成这个插件。

2 Comments

  1. 泡澡 2011年12月30日
    • DevBean 2011年12月30日

Leave a Reply