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()
函数用于实现真实的“查找”操作。我们需要了解ProjectExplorer
、TextEditor
、Find
和Core::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 一项。注意在范围下拉框中的显示以及对话框下方的配置组件。
现在,由于我们的findAll()
函数没有实现,我们仅仅为对话框提供了一个没有“查找”功能的界面。在后面的章节中,我们将继续完成这个插件。
2 评论
我晕了,好复杂啊
复杂的系统就有复杂的架构呗…嘻嘻