Qt Creator 最基本的功能是一个文本编辑器。在此基础之上,Qt Creator 还提供了编辑 UI 文件、QRC 文件、PRO/PRI 文件以及 EXE/DLL/SO 文件的功能。
从本节开始,我们将开始尝试开发一些实际的插件,理解如何为我们特有的文件格式提供编辑器。这里,我们选择 HTML 格式。我们的插件将使我们能够从本地文件系统中加载 HTML 文件,并且能够查看和编辑。下面就是我们的插件完成后的行为:
核心类和接口
为了支持新的编辑器类型,我们需要:
- 实现一个插件类(实现
Core::IPlugin
接口),暴露出一个“编辑器工厂”。前面我们已经介绍过如何创建插件,实现Core::IPlugin
接口。 - 实现这个“编辑器工厂”,也就是
Core::IEditorFactory
接口。这个接口提供了帮助创建特定格式编辑器对象的函数。 - 实现编辑器,也就是
Core::IEditor
接口。这个接口提供了用于辅助编辑一种文件格式(例如 HTML、ODF 等)的函数。编辑器必须提供访问它所要显示或者编辑的文件的函数。 - 实现接口
Core::IFile
。该接口用于帮助数据加载或保存。
在后面的内容中,我们将依次了解上述各个接口的含义以及如何实现这些接口。
Core::IFile
Core::IFile
接口将文件操作从用户界面抽象出来,提供用于加载和保存文件的虚函数(一般会以文件名作为参数)。我们可以将文件看做具有 mime-tyle、“modified” 和 “read-only” 等标记位的对象。Core::IFile
接口在 src/plugins/coreplugin/ifile.h 中声明:
#ifndef IFILE_H #define IFILE_H #include "core_global.h" #include <QtCore/QObject> namespace Core { class MimeType; class CORE_EXPORT IFile : public QObject { Q_OBJECT public: // This enum must match the indexes of the reloadBehavior widget // in generalsettings.ui enum ReloadSetting { AlwaysAsk = 0, ReloadUnmodified = 1, IgnoreAll = 2 }; enum Utf8BomSetting { AlwaysAdd = 0, OnlyKeep = 1, AlwaysDelete = 2 }; enum ChangeTrigger { TriggerInternal, TriggerExternal }; enum ChangeType { TypeContents, TypePermissions, TypeRemoved }; enum ReloadBehavior { BehaviorAsk, BehaviorSilent }; enum ReloadFlag { FlagReload, FlagIgnore }; IFile(QObject *parent = 0) : QObject(parent) {} virtual ~IFile() {} virtual bool save(const QString &fileName = QString()) = 0; virtual QString fileName() const = 0; virtual QString defaultPath() const = 0; virtual QString suggestedFileName() const = 0; virtual QString mimeType() const = 0; virtual bool isModified() const = 0; virtual bool isReadOnly() const = 0; virtual bool isSaveAsAllowed() const = 0; virtual ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const = 0; virtual void reload(ReloadFlag flag, ChangeType type) = 0; virtual void rename(const QString &newName) = 0; virtual void checkPermissions() {} signals: void changed(); void aboutToReload(); void reloaded(); }; } // namespace Core #endif // IFILE_H
或许你会问:“我们已经有QFile
,作为文件操作的一种抽象,为什么又要设计一个IFile
呢?”原因如下:
IFile
关心的是以文件名为参数,将一个文件的内容加载进一个编辑器 editor 的行为,而QFile
仅仅是将文件内容加载到一个QByteArray
对象;IFile
需要在用户在编辑器中修改了文件内容的时候发出modified()
信号,需要注意的是,此时的文件修改并没有写入磁盘;而QFile
只有在文件内容写入磁盘时才会发出bytesWritten()
信号;IFile
需要处理一个在磁盘被修改的文件如何重新加载到编辑器中,而QFile
不需要处理这种问题
我们会在后面的章节中详细探讨如何实现Core::IFile
接口。
Core::IEditor
Core::IEditor
接口用于提供编辑不同类型文件的编辑器。这个接口位于 src/plugins/coreplugin/editormanager/ieditor.h 中:
#ifndef IEDITOR_H #define IEDITOR_H #include <coreplugin/core_global.h> #include <coreplugin/icontext.h> #include <QtCore/QMetaType> namespace Core { class IFile; class CORE_EXPORT IEditor : public IContext { Q_OBJECT public: IEditor(QObject *parent = 0) : IContext(parent) {} virtual ~IEditor() {} virtual bool createNew(const QString &contents = QString()) = 0; virtual bool open(const QString &fileName = QString()) = 0; virtual IFile *file() = 0; virtual QString id() const = 0; virtual QString displayName() const = 0; virtual void setDisplayName(const QString &title) = 0; virtual bool duplicateSupported() const = 0; virtual IEditor *duplicate(QWidget *parent) = 0; virtual QByteArray saveState() const = 0; virtual bool restoreState(const QByteArray &state) = 0; virtual int currentLine() const { return 0; } virtual int currentColumn() const { return 0; } virtual void gotoLine(int line, int column = 0) { Q_UNUSED(line) Q_UNUSED(column) } virtual bool isTemporary() const = 0; virtual QWidget *toolBar() = 0; virtual QString preferredModeType() const { return QString(); } signals: void changed(); }; } // namespace Core Q_DECLARE_METATYPE(Core::IEditor*) #endif // IEDITOR_H
Core::IEditor
主要提供以下功能:
- 一个编辑器组件(由
Core::IEditor::widget()
函数返回)。Qt Creator 使用这个组件显示需要编辑的文件的内容; - 实现
Core::IFile
接口的文件(由Core::IEditor::file()
函数返回),Qt Creator 使用这个对象触发文件从磁盘加载以及保存到磁盘的操作; - 一个自定义的工具条 toolbar,Qt Creator 会在该编辑器可用时自动加载该工具条;
- 在文件中光标的当前位置(
Core::IEditor::currentLine()
和Core::IEditor::currentColumn()
函数) - 需要显示在“打开文件”列表的名字。
我们可以通过下面的示意图来理解上面说的这几点:
2 评论
豆子老大我又来了,IFile.h在qtcreator里似乎改成了IDocument.h,不知到是不是?
在最新版本中是有了修改