2010-09-28

QtCreator-XmlTree: Редактор

Итак, мы создали скелет проекта и теперь нам надо его наполнить. Для начала определимся что нам необходимо отнаследовать для создания своего редактора:
  • Core::IEditor
  • Core::IFile
  • Core::IEditorFactory
Ну и плюс к этому необходимо дописать уже созданного наследника ExtensionSystem::IPlugin и реализовать само дерево для отображения xml.

Отображение дерева
На эту роль как нельзя лучше подходит связка наследников классов QTreeViewQAbstractItemModel и QStyledItemDelegate. Останавливаться на них подробно я не буду, ничем особым они не примечательны в контексте данного цикла. Единственное что необходимо отметить это наличие у наследника QTreeView методов:
    void setContent(const QByteArray &ba);
    QByteArray content();
Они понадобятся позже для установки и получения текста xml-файла.

Короткое отступление
Реализации нижеследующих классов тривиальны и я не буду их приводить. Полные исходники всегда можно посмотреть на gitorious.

Наследник Core::IEditor
В этом классе реализуются методы для работы с содержимым редактора и для управления самим редактором. В нем нам необходимо заполнить контекст и по сути все. Все методы являются оберткой либо над другими классами, либо над состоянием объекта.
class XmlEditor : public Core::IEditor
{
    Q_OBJECT
public:
    explicit XmlEditor(XmlEditorWidget *editorWidget);
    ~XmlEditor();

    // Методы для установки и получения содержимого файла.
    // Являются обертками над соответствующими методами виджета
    QByteArray rawContent();
    void setRawContent(const QByteArray &data);

    // Возвращает контест редактора
    Core::Context context() const;
    
    // Возвращает сам виджет редактора.
    // В нашем случае экземпляр наследника QTreeView
    QWidget *widget();

    // Вызывается при создании нового файла в редакторе
    bool createNew(const QString &contents = QString());
    // Вызывается при открытии файла в редакторе
    bool open(const QString &fileName = QString());
    // Возвращает используемый указатель на IFile
    Core::IFile *file();
    // Возвращает идентификатор редактора (нужен для создания контекста)
    QString id() const;
    // Установка и получение названия редактора
    // для отображения в контекстном меню файла
    QString displayName() const;
    void setDisplayName(const QString &title);

    // Есть ли поддержка дубликатов редактора
    bool duplicateSupported() const;
    // Указатель на дубликат (если поддерживается)
    Core::IEditor *duplicate(QWidget *parent);

    // Сохранение и восстановление состояния редактора
    QByteArray saveState() const;
    bool restoreState(const QByteArray &state);

    // Текущая строка файла
    int currentLine() const;
    // Текущий символ в строке файла
    int currentColumn() const;

    // Является ли файл в редакторе временным
    bool isTemporary() const;

    // Тулбар редактора
    QWidget *toolBar();

    // Предпочитаемый режим работы
    QString preferredModeType() const;

signals:

public slots:

protected:
    QScopedPointer<QObjectData> d_ptr;

private:
    Q_DECLARE_PRIVATE(XmlEditor)

};

Наследник Core::IFile
В этом классе реализуется логика работы с открытым в редакторе файлом: открытие, сохранение, параметры файла, обновление содержимого файла в редакторе при его изменении при различных факторах, переименование.
class XmlFile : public Core::IFile
{
    Q_OBJECT
public:
    explicit XmlFile(XmlEditor *editor);
    ~XmlFile();

    // Установка флага изменения содержимого относительно
    // первоначального файла
    void setModified(bool value = true);
    // Откртыие файла
    bool open(const QString &fileName = QString());
    // Сохранение файла
    bool save(const QString &fileName = QString());
    // Получение и установка имени текущего файла
    void setFileName(const QString &value);
    QString fileName() const;
    
    // Путь по умолчанию для открытия/сохранения файла
    QString defaultPath() const;
    // Имя файла при сохранении, предлагаемое редактором
    QString suggestedFileName() const;
    // MIME-тип файла
    QString mimeType() const;
    
    // Было ли содержимое модифицировано относительно
    // первоначального файла
    bool isModified() const;
    // Открыт ли файл только для чтения
    bool isReadOnly() const;
    // Разрешено ли сохранени копии файла под другим именем
    bool isSaveAsAllowed() const;

    // Какие действия производить при изменении содержимого файла
    // или его аттрибутов извне или изнутри QtCreator
    Core::IFile::ReloadBehavior reloadBehavior(ChangeTrigger state, 
                                               ChangeType type) const;
    // Действия при обновлении файла
    void reload(ReloadFlag flag, ChangeType type);
    // Действия при переименовании файла
    void rename(const QString &newName);

    // Проверка прав на доступ к файлу
    void checkPermissions();

protected slots:
    // Взведение флага модификации содержимого
    void modified() {setModified(true);}

protected:
    QScopedPointer<QObjectData> d_ptr;

private:
    Q_DECLARE_PRIVATE(XmlFile)

};

Наследник Core::IEditorFactory
Этот класс является небольшой абстракцией над двумя выше обозначенными и нужен для начала работы с редактором .
class XmlEditorFactory : public Core::IEditorFactory
{
    Q_OBJECT
public:
    explicit XmlEditorFactory(
        XmlTreePlugin::Internal::XmlTreePluginImpl *owner);

    // MIME-типы, которые можно открыть редактором
    QStringList mimeTypes() const;

    // Идентификатор редактора (нужен для создания контекста)
    QString id() const;
    // Название редактора, отображаемое в контекстном меню файла
    QString displayName() const;

    // Открытие файла
    Core::IFile *open(const QString &fileName);
    // Создание редактора
    Core::IEditor *createEditor(QWidget *parent);


protected:
    QScopedPointer<QObjectData> d_ptr;

private:
    Q_DECLARE_PRIVATE(XmlEditorFactory)
};


Наследник ExtensionSystem::IPlugin
Теперь нам осталось только прописать MIME-типы (о них будет в следующей статье) в методе initialize() и оповестить из него QtCreator о нашем редакторе:
addAutoReleasedObject(new XmlEditorFactory(this));

Комментариев нет:

Отправить комментарий