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,不知到是不是?
在最新版本中是有了修改