Описание решения
Итак, какое решение нас устроит? Вполне достаточно чтобы в Open Documents и по Ctrl+Tab появлялись не просто __init__.js всей своей массой, а также было указано в какой директории лежит этот файл (например someext/__init__.js). Ничто не мешает конечно поменять количество папок в префиксе или приписать что-то свое.
MIME-тип
Итак, первое что нам необходимо сделать это прицепиться к нужным нам файлам, предоставляя стандартный QmlJSEditor для всех остальных js-файлов. Ну тут все просто, нам надо всего лишь задать подтип обычного javascript с конкретным паттерном файла (в нашем случае это как раз будет __init__.js).
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="application/x-script-extension-javascript">
<sub-class-of type="application/javascript"/>
<comment>Qt Script Extension init file</comment>
<glob pattern="__init__.js"/>
</mime-type>
</mime-info>
Наследник IPlugin
Сначала приведу полный код метода initialize(), ну а потом уже разберем что в нем происходит.
bool ScriptExtensionsEditorPluginImpl::initialize(const QStringList &arguments, QString *errorString) {
Q_UNUSED(arguments) Core::ICore *core = Core::ICore::instance(); if (!core->mimeDatabase()->addMimeTypes( QLatin1String(":/seeditor/SEEditor.mimetypes.xml"), errorString)) return false; m_modelManager = QmlJS::ModelManagerInterface::instance(); m_editor = new ScriptExtensionsEditorFactory(this); addObject(m_editor); m_actionHandler = new TextEditor::TextEditorActionHandler( "BlackTass.SEEditor", TextEditor::TextEditorActionHandler::Format | TextEditor::TextEditorActionHandler::UnCommentSelection | TextEditor::TextEditorActionHandler::UnCollapseAll); m_actionHandler->initializeActions(); QmlJSEditor::Internal::CodeCompletion *completion = new QmlJSEditor::Internal::CodeCompletion(m_modelManager); addAutoReleasedObject(completion); // Set completion settings and keep them up to date TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance(); completion->setCompletionSettings( textEditorSettings->completionSettings()); connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)), completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings))); return true; }
|
SOURCES += \ $$QTCREATOR_SOURCES/src/plugins/qmljseditor/qmljscodecompletion.cpp
HEADERS +=\ $$QTCREATOR_SOURCES/src/plugins/qmljseditor/qmljscodecompletion.h
|
Также нам необходимо сделать метод, который будет непосредственно настраивать редактор, назовем его initializeEditor():
void ScriptExtensionsEditorPluginImpl::initializeEditor( ScriptExtensionsEditor *editor) {
QTC_ASSERT(m_instance, /**/); m_actionHandler->setupActions(editor); TextEditor::TextEditorSettings::instance()->initializeEditor(editor); // auto completion connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)), TextEditor::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool))); }
|
Непосредственно редактор
Для реализации редактора в QtCreator, как известно нужны минимум три класса: фабрика, сам редактор и editable (который отслеживает различные операции с файлами и взаимодействия с редактором). На фабрике особо останавливаться не буду, напомню только что в createEditor() необходимо вызвать initializeEditor() из экземпляра класса рассмотренного выше.
В editable необходимо не забыть возвращать правильный контекст (который должен содержать наш плагин и текстовый редактор), чтобы правильно работали все горячие клавиши:
ScriptExtensionsEditorEditable::ScriptExtensionsEditorEditable( ScriptExtensionsEditor *editor) : QmlJSEditor::QmlJSEditorEditable(editor) {
m_context.add("BlackTass.SEEditor"); m_context.add(TextEditor::Constants::C_TEXTEDITOR); }
Core::Context ScriptExtensionsEditorEditable::context() const {
return m_context; }
|
Сам слот достаточно прост. Он проверяет является ли текущий файл extension'ом (а это очень легко проверить по пути файла, в нем должна быть папка qtscriptextension и сам файл должен называться __init__.js) и если подходит, то дописывает перед названием файла имя папки, в которой он лежит. После этого в очередь событий кладется изменение displayName (который и отвечает за надписи во всех нужных нам местах) для того чтобы наше изменение было гарантированно последним.
void ScriptExtensionsEditor::onTitleChanged(const QString &title) {
Q_UNUSED(title); QString fileName = baseTextDocument()->fileName(); if (fileName.contains(QRegExp("qtscriptextension.*__init__\\.js$"))) { QFileInfo fi(fileName); QString realTitle = fi.dir().dirName()+"/"+fi.fileName(); QMetaObject::invokeMethod(this, "setDisplayName", Qt::QueuedConnection, Q_ARG(QString, realTitle)); } }
|
Итог
В итоге мы имеем небольшой плагин (суммарное количество кода в районе 350 строк), который не нарушает приятный функционал QmlJSEditor и дает возможность легче работать с extension'ами.
Внимание! Подобные плагины не будут работать в 2.0 и скорее всего не будут в 2.1. В них editable у QmlJSEditor являлся также внутренним классом и только потом его заэкспортили в библиотеку.
Делайте отступы в коде, а то он становится нечетабельным.
ОтветитьУдалитьА так все кул)
Хехе, да они съедаются при копипасте из редактора. Постоянно забываю расставлять по новой.
ОтветитьУдалить