GalaPlugin-QtCreatorのJS / QMLプラグイン

プラグインのQtCreator + 2モードパネルを使用して投稿読んだ後、JavaScriptとQMLを使用してQtCreatorの機能を拡張できるプラグインを作成しようと考えました。 GalaPluginプロジェクトが登場しました



これは何が起こったのかを示す小さなデモです。







仕組み



このプラグインのアイデアは非常に単純です-初期化中、 bool initialize(const QStringList &arguments, QString *errorString)



関数bool initialize(const QStringList &arguments, QString *errorString)



で、プラグインフォルダー内の特別な「スクリプト」プラグインを探します。 これらは* .gala拡張子を持つJavaScriptファイルであり、次の構成要素が含まれる場合があります。



  1. 必須の関数initialize()



    は、スクリプトをロードした直後に呼び出されます。
  2. オプションのextensionsInitialized()



    関数。メインプラグインの対応する関数で呼び出されます(すべてのプラグインがロードされた場合)。
  3. オプションのaboutToShutdown()



    関数。QtCreatorを閉じる前に呼び出されます。
  4. オプションの整数変数galaPluginOrder



    。起動時にスクリプトプラグインの順序を変更するために使用されます。
  5. オプションのブール変数galaPluginDisable



    を使用すると、スクリプトプラグインを無視できます。
  6. オプションのブール変数galaPluginTrace



    。これにより、すべてのgalaPluginTrace



    呼び出しをログに記録できます(デバッグに役立ちます)。


モードバーに[すべて保存]ボタンを追加するSaveAllBttn.galaスクリプトプラグインの例を次に示します

SaveAllBttn.gala
 var galaPluginOrder = 1; var galaPluginTrace = true; function saveAllAction() { var docs = editorManager.documents(); for (var i = 0; i < docs.length; ++i) { var doc = docs[i]; if (doc.isModified()) { doc.save("", false); } } } function createSaveAllButton() { var bttn = galaAPI.createQObject("QPushButton", modeManager); bttn.flat = true; bttn.text = "Save All"; bttn.focusPolicy = 0; bttn.styleSheet = "QPushButton {color: white; }"; // disable button minimum width bttn.sizePolicy = galaAPI.sizePolicy(13, 0, 1); bttn.clicked.connect(saveAllAction); return bttn; } function initialize() { modeManager.addWidget(createSaveAllButton()); galaAPI.debug("Success initialize"); } function extensionsInitialized() { galaAPI.debug("Success extensionsInitialized"); } function aboutToShutdown() { galaAPI.debug("Success aboutToShutdown"); }
      
      







さらに、さらに4つのスクリプトプラグインを使用できます。



スクリプトからQtCreator APIを使用するために、必要なクラス( Core::ICore



Core::Command



Core::ActionManager



など)のラッパーを作成しました。 ラッパーを作成するプロセスはほとんど機械的です。QObjectの下位クラスを作成し、QtCreator APIからクラスへのポインターを渡し、保存し、パブリックスロットセクションでラッパーのソースクラスのすべてのパブリックメソッドを呼び出します。



以下に小さな例を示します。
 class GModeManager : public GWrapper { Q_OBJECT public: GModeManager(QJSEngine* jsEngine) : GWrapper(jsEngine), m_owner(qobject_cast<Core::ModeManager*>(Core::ModeManager::instance())) { Q_ASSERT(m_owner); } ~GModeManager() {} Core::ModeManager* owner1() { return m_owner; } public slots: QJSValue owner() { return m_jsEngine->toScriptValue(m_owner); } QJSValue currentMode() { return m_jsEngine->toScriptValue(m_owner->currentMode()); } QJSValue mode(QString id) { return m_jsEngine->toScriptValue(m_owner->mode(str2id(id))); } void addAction(QAction *action, int priority) { m_owner->addAction(action, priority); } void addProjectSelector(QAction *action) { m_owner->addProjectSelector(action); } void addWidget(QWidget *widget) { m_owner->addWidget(widget); } void activateMode(QString id) { m_owner->activateMode(str2id(id)); } void setFocusToCurrentMode() { m_owner->setFocusToCurrentMode(); } bool isModeSelectorVisible() { return m_owner->isModeSelectorVisible(); } void setModeSelectorVisible(bool visible) { m_owner->setModeSelectorVisible(visible); } private: Core::ModeManager* m_owner; };
      
      







オブジェクトへのポインタのリストを返す関数は少し複雑です。JavaScript配列値にパックする必要があります。 editorManager.documents()



関数の実装例は次のeditorManager.documents()



です。



 QJSValue documents() { QList<Core::IDocument *> documents = m_owner->documentModel()->openedDocuments(); QJSValue array = m_jsEngine->newArray(documents.size()); for (quint32 i = 0; i < (quint32)documents.size(); ++i) { array.setProperty(i, m_jsEngine->newQObject(new GDocument(m_jsEngine, documents[i]))); } return array; }
      
      







現在、JavaScript / QML環境では、次のグローバルオブジェクトを使用できます。



  1. core - Core::ICore::instance()



    表しCore::ICore::instance()



  2. messageManager - Core::MessageManager::instance()



    表しCore::MessageManager::instance()



  3. actionManager - Core::ActionManager::instance()



    表しCore::ActionManager::instance()



  4. editorManager - Core::EditorManager:instance()



    導入しCore::EditorManager:instance()



  5. modeManager- Core::ModeManager::instance()



    表しCore::ModeManager::instance()



  6. galaAPI-補助的な便利な機能へのアクセスポイントとして機能


プラグインの作成中に、次の問題が発生しました。

スロットがQObject継承オブジェクトへのポインターを返す場合、JavaScript環境はこのオブジェクトの所有権を取得します。 これは、スロットがラッパーを作成してJSコードに返す場合に便利です。 例えば



 GCommand *command(QString id) { return new GCommand(m_jsEngine, m_owner->command(str2id(id))); }
      
      





スロットが内部QtCreatorオブジェクトを返す場合、環境はそれを所有してはなりません。 このような場合、オブジェクトへのポインターではなく、ポインターをラップするQJSValueを返す必要があります。



 //  QMenu* QJSValue menu() const { return m_jsEngine->toScriptValue(static_cast<QObject*>(m_owner->menu())); }
      
      







JSでのシグナル転送に関する別の問題は、デフォルトのパラメーターと同じメソッド名です。



メソッドfoo



がJSから呼び出されると、その名前のメソッドがオブジェクトのメタシステムで検索され、最初のメソッドが呼び出されます。 パラメーターの数(特にタイプ)の比較はありません。 この場合、信号にデフォルトのパラメーターがある場合、mocはいくつかのメタメソッドを生成します。 たとえば、シグナルvoid foo(int a, int b = 0, int c = 1);



3つのメタメソッドが生成されます

 void foo(int a); void foo(int a, int b); void foo(int a, int b, int c);
      
      





そして、この順序で-最初の最短バージョンです。 したがって、JSでデフォルトのパラメーターを使用することはできず、すべてのパラメーターを手動で渡す必要があります。 そして、同じ名前のメソッドを一意にします。



おわりに



このプラグインを使用すると、QtCreator'aの機能を非常に簡単に拡張できます。 モードパネルで視覚要素を作成し、頻繁に使用するコマンドや特定のコマンドのツールバーとメニュー項目を作成する際に、スクリプトプラグインの主な使用法を見ています。 QMLオブジェクトを埋め込む機能は、素晴らしい機会を提供します。 天気、為替レート、お気に入りのリソースに関する新しい記事、スポーツのアカウント、ビルドステータスなど、あらゆるWebサービスを監視するQMLビューを簡単に作成できます。 私はQMLの専門家ではありませんが、ネット上には多くの興味深い例があります。



面白いアイデアをお持ちの場合、またはさらに良いことに、興味深いスクリプトプラグインを実装している場合は、コミュニティで共有してください。 私は自分のプロジェクトにそれを追加させていただきます。



また、さまざまなプラットフォーム用にプラグインをコンパイルする際に助けを求めます。 Windowsの場合、問題はLinuxの場合と同様に簡単に構築できます。 MacOSでは、ビルドする方法はまったくありません。



PS最後まで読んだ人のためのPS、別のビデオ:




All Articles