Qt Creator 插件开发(12):添加新的编辑器(续四)

Core::IEditor

HtmlEditor类实现了IEditor接口。这个接口提供一个编辑器组件,用于编辑 HTML 文件。我们还需要将一个HtmlFile实例与其关联起来:

#ifndef HTMLEDITOR_H
#define HTMLEDITOR_H

#include <coreplugin/editormanager/ieditor.h>

struct HtmlEditorData;

class QToolBar;

class HtmlEditorWidget;
class HtmlFile;

namespace HtmlEditorConstants
{
    const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
    const char* const C_HTMLEDITOR          = "HTML Editor";
};

class HtmlEditor : public Core::IEditor
{
    Q_OBJECT
public:
    HtmlEditor(HtmlEditorWidget* editorWidget);
    ~HtmlEditor();
    bool createNew(const QString& /*contents*/ = QString());
    QString displayName() const;
    QString id() const { return HtmlEditorConstants::C_HTMLEDITOR; }
    IEditor* duplicate(QWidget* /*parent*/);
    bool duplicateSupported() const;
    Core::IFile* file();
    bool isTemporary() const;
    const char* kind() const;
    bool open(const QString& fileName = QString());
    bool restoreState(const QByteArray& /*state*/);
    QByteArray saveState() const;
    void setDisplayName(const QString &title);
    QWidget* toolBar();
    QWidget* widget();
    Core::Context context() const;

protected slots:
    void slotTitleChanged(const QString& title) { setDisplayName(title); }

private:
    HtmlEditorData* d;
};

struct HtmlEditorData
{ 
    HtmlEditorData() : editorWidget(0), file(0) { }
    HtmlEditorWidget* editorWidget;
    QString displayName;
    HtmlFile* file;
    Core::Context context;
};

#endif // HTMLEDITOR_H

HtmlEditorData保存一个HtmlEditorWidget对象和一个HtmlFile对象。displayName属性用于显示该文档的可视化描述:

struct HtmlEditorData
{ 
    HtmlEditorData() : editorWidget(0), file(0) { }
    HtmlEditorWidget* editorWidget;
    QString displayName;
    HtmlFile* file;
    Core::Context context;
};

构造函数用于初始化HtmlEditorWidget实例。同时,它还创建一个HtmlFile实例,这样就可以将其与HtmlEditor和 widget 关联起来:

HtmlEditor::HtmlEditor(HtmlEditorWidget* editorWidget)
           : Core::IEditor(editorWidget)
{
    d = new HtmlEditorData;
    d->editorWidget = editorWidget;
    d->file = new HtmlFile(this, editorWidget);
    d->context = Core::Context(HtmlEditorConstants::C_HTMLEDITOR);
    connect(d->editorWidget, SIGNAL(contentModified()),
            d->file,         SLOT(modified()));
    connect(d->editorWidget, SIGNAL(titleChanged(QString)),
                             SLOT(slotTitleChanged(QString)));
    connect(d->editorWidget, SIGNAL(contentModified()),
                             SIGNAL(changed()));
}

析构函数不作任何操作,仅仅删除 d 指针:

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

下面是一些不需要解释的函数:

QWidget* HtmlEditor::widget()
{
    return d->editorWidget;
}

Core::Context HtmlEditor::context() const
{
    return d->context;
}

Core::IFile* HtmlEditor::file()
{
    return d->file;
}

createNew()函数用于重新设置HtmlEditorWidget的内容以及HtmlFile对象。现在,我们只是简单地忽略contents参数:

bool HtmlEditor::createNew(const QString& contents)
{
    Q_UNUSED(contents);
    d->editorWidget->setContent(QByteArray());
    d->file->setFilename(QString());
    return true;
}

open()函数请求HtmlFile打开一个给定文件名的文件。它假设filename就是一个 HTML 文件的名字:

bool HtmlEditor::open(const QString &fileName)
{
    return d->file->open(fileName);
}

下面的函数则用于返回编辑器的“类型”:

namespace HtmlEditorConstants
{
    const char* const C_HTMLEDITOR_MIMETYPE = "text/html";
    const char* const C_HTMLEDITOR          = "HTML Editor";
};
// ......
const char* HtmlEditor::kind() const
{
    return HtmlEditorConstants::C_HTMLEDITOR;
}

displayName()函数返回的字符串用于显示在打开文件列表中。下面的函数帮助设置和获取这个显示的名字:

QString HtmlEditor::displayName() const
{
    return d->displayName;
}

void HtmlEditor::setDisplayName(const QString& title)
{
    if(d->displayName == title)
        return; 
    d->displayName = title;
    emit changed();
}

下面几个函数仅仅是为了给出纯虚函数的一个默认实现,在我们这个简单的例子中不作任何操作:

bool HtmlEditor::duplicateSupported() const
{
    return false;
}

Core::IEditor* HtmlEditor::duplicate(QWidget* parent)
{
    Q_UNUSED(parent);
    return 0;
}

QByteArray HtmlEditor::saveState() const
{
    return QByteArray();
}

bool HtmlEditor::restoreState(const QByteArray& state)
{
    Q_UNUSED(state);
    return false;
}

QWidget* HtmlEditor::toolBar()
{ 
    return 0;
}

bool HtmlEditor::isTemporary() const
{
    return false;
}

Core::IEditorFactory

HtmlEditorFactory实现了Core::IEditorFactory接口:

#ifndef HTMLEDITORFACTORY_H
#define HTMLEDITORFACTORY_H

#include <coreplugin/editormanager/ieditorfactory.h>

#include "HtmlEditor.h"

struct HtmlEditorFactoryData;

class HtmlEditorPlugin;

class HtmlEditorFactory : public Core::IEditorFactory
{
    Q_OBJECT
public:
    HtmlEditorFactory(HtmlEditorPlugin* owner);
    ~HtmlEditorFactory();
    QStringList mimeTypes() const;
    QString kind() const;
    Core::IEditor* createEditor(QWidget* parent);
    Core::IFile* open(const QString &fileName);
    QString id() const { return QString("HTML Editor Factory ID"); }
    QString displayName() const { return QString("HTML Editor Factory"); }
private:
    HtmlEditorFactoryData* d;
};

struct HtmlEditorFactoryData
{
    HtmlEditorFactoryData()
        : kind(HtmlEditorConstants::C_HTMLEDITOR)
    {
        mimeTypes << QString(HtmlEditorConstants::C_HTMLEDITOR_MIMETYPE);
    }

    QString kind;
    QStringList mimeTypes;
};

#endif // HTMLEDITORFACTORY_H

HtmlEditorFactoryData用于保存HtmlEditorFactory类的私有成员变量。注意,构造函数将其 mime-types 初始化为HtmlEditorConstants::C_HTMLEDITOR_MYMETYPE;同时,我们也设置了 editor 的类型,这个类型同前面所说的HtmlEditor的类型是一致的:

struct HtmlEditorFactoryData
{
    HtmlEditorFactoryData()
        : kind(HtmlEditorConstants::C_HTMLEDITOR)
    {
        mimeTypes << QString(HtmlEditorConstants::C_HTMLEDITOR_MIMETYPE);
    }

    QString kind;
    QStringList mimeTypes;
};

下面几个函数则无需过多解释:

HtmlEditorFactory::HtmlEditorFactory(HtmlEditorPlugin* owner)
                  :Core::IEditorFactory(owner)
{
    d = new HtmlEditorFactoryData;
}

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

QStringList HtmlEditorFactory::mimeTypes() const
{
    return d->mimeTypes;
}

QString HtmlEditorFactory::kind() const
{
    return d->kind;
}

还记得我们前面说过,IFileIEditor是关联在一起的。open()函数就是返回正在处理这个文件名指定的IFile实例。如果没有,则会创建一个新的编辑器用于处理这个文件,同时将IFile返回。如果要全部理解这个过程,可以查阅Core::EditorManager::openEditor()函数的实现:

Core::IFile* HtmlEditorFactory::open(const QString& fileName)
{
    Core::EditorManager* em = Core::EditorManager::instance();
    Core::IEditor* iface = em->openEditor(fileName, d->kind);
    return iface ? iface->file() : 0;
}

下面的函数用于创建和返回HtmlEditor实例:

Core::IEditor* HtmlEditorFactory::createEditor(QWidget* parent)
{
    HtmlEditorWidget* editorWidget = new HtmlEditorWidget(parent);
    return new HtmlEditor(editorWidget);
}

实现插件

在前面的章节中,我们已经知道了实现插件的方法。现在我们使用和前面一样的方法实现HtmlEditorPlugin插件类。唯一的区别是initialize()函数的实现:

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

    Core::ICore* core = Core::ICore::instance();
    Core::MimeDatabase* mdb = core->mimeDatabase();
    if(!mdb->addMimeTypes("text-html-mimetype.xml", errMsg))
        return false;
    addAutoReleasedObject(new HtmlEditorFactory(this));

    return true;
}

最后,按照我们前面所写的过程去编译吧!

附件下载:HtmlEditor 插件文件

8 Comments

  1. Brian 2011年11月15日
    • DevBean 2011年11月15日
    • fengyun_52 2011年12月13日
      • DevBean 2011年12月14日
  2. 小马 2011年12月31日
    • DevBean 2011年12月31日
  3. 王显灿 2016年8月29日
    • 豆子 2016年8月30日

Leave a Reply