まえがき
みなさんこんにちは。 ずっと前にこの投稿を書き始めたことをすぐに認めなければなりませんが、完全に書き終えるのに十分な時間はありません。 したがって、現在は現在の状態で公開していますが、3つの不完全なセクションの説明を延期し、別の投稿として公開しようとしています。
はじめに
これは、Qt Creator開発環境のアーキテクチャと拡張システムについて少し説明したいメモです。 最初は、 Writing-Qt-Cretor-plugins.pdfドキュメントを翻訳することだけを意図していましたが、Qt Creatorの開発が止まっていないことがわかりました。完全であり、多くの場合は機能しません)、そして第二に、その執筆時点から、追加のQt Creator拡張機能について説明します。
それにもかかわらず、このドキュメントがなければ、このメモはありませんでした:投稿の構造まで、そこから多くのものを取って、何かを投げたり、置き換えたり、追加したりして、今のところ後者に関連するようにしますQt Creator 2.4.0のタイムバージョン。
このドキュメントの恩恵を受けることができるのは誰ですか? まず第一に、これらはもちろんこのIDEをメイン開発環境として選択したQtプログラマーです。
さらに、よく考え抜かれたQt Creator拡張システムのおかげで、この資料は独自の開発ツールを作成しようとしているが、ゼロから作成を開始したくない場合に役立ちます。不要なQt Creator拡張機能をすべて無効にして、独自のQt Creatorのソースコードの既製のサンプル。
それで、カットの下で私たちを待っています(準備ができているセクションは太字でマークされています):
- ビルドQt Creator
- 最初の拡張子
- 新しいメニューとメニュー項目の追加
- Qt Creatorのアーキテクチャ
- 新しいエディターの追加
- サイドナビゲーションバーの追加
- 設定ダイアログへのページの追加
- 検索ダイアログへのフィルターの追加
- 新しいプロジェクトタイプの追加
Qt Creatorは、Trolltech(Nokia)によって開発されたQtフレームワークを操作するためのクロスプラットフォームの無料IDEであることを思い出させてください。 シンタックスハイライト、すべての拡張機能の単純な無効化を備えたシンプルなテキストエディタにすることを妨げないもの。 注意、何百枚もの写真!
1. Qt Creatorをビルドする
IDE全体を組み立てるのは非常に簡単なアクションです。 まず、Qt Creatorの最新バージョンのソースコードをダウンロードする必要があります。 これは現在バージョン2.4です。 Downloads / Qt-Creatorセクションからqt.nokia.comからファイルをダウンロードします。
次に、結果のアーカイブを解凍し、ソースディレクトリにbuildサブディレクトリを作成し、そこに移動して、qmakeを実行してからmakeを実行します。
$ tar -xvf qt-creator-2.4.0-src.tar.gz $ mkdir qt-creator-2.4.0-src/build $ cd qt-creator-2.4.0-src/build/ $ qmake ../qtcreator.pro –recursive $ make
Windowsユーザーの場合、このコードは最後の行でのみ異なる場合があります-makeではなく、ユーザーの設定に応じてmingw32-makeまたはnmakeを呼び出す必要があります。
以上です。 build / binディレクトリからQt Creatorを実行できます。
ソースからQt Creatorをコンパイルしないと、それ以上拡張機能をコンパイルしてテストすることができないため、これは非常に重要な段階であることに注意してください。
2.最初の拡張子
多くの場合、非常に単純な拡張機能を作成して、Qt Creator拡張システムの調査を開始する必要があります。 ここでは、何もしない拡張機能を作成しようとしますが、DoNothing拡張機能の例を使用して、拡張機能の作成に関連するQt Creatorの基本クラスについて学習し、利用可能な拡張機能のリストの「DoNothing」行を確認します。
2.1 Qt Creator拡張プロジェクトの作成
以前は、バージョン2.0までのようでした。この手順を完了するには、次のファイルを手動で作成する必要がありました。
- DoNothingPlugin.pro
- DoNothingPlugin.h
- DoNothingPlugin.cpp
- DoNothingPlugin.pluginspec
また、拡張プロジェクトを$$ QT_CREATOR_ROOT / src / pluginsディレクトリに配置するか、別の場所に配置して、.proファイルでQt Creatorのソースディレクトリとビルドを指定する必要があります。 Qt Creatorの最新バージョンでは、新しいタイプのウィザード-それを作成する「Qt Creator Module」が登場したため、プロジェクトファイルはどこにでも配置できます。 現在、新しい拡張機能を作成するプロセスは次のとおりです/
最初は、すべてが通常通りです-作成するプロジェクトのタイプを選択し、
配置のディレクトリへの名前とパスを入力した後
アセンブリの目的と同様に、これは当然デスクトップです。
しかし、その後、小さな魔法が始まります-モジュールに固有の情報を記入する必要があります:
ここでは、一般的に、すべてが写真から明らかです。 ここでの唯一の重要なフィールドは、Qt Creatorのソース/ビルドディレクトリへのパスです。 ウィザードを完了します。
そして、結果のプロジェクト構造を見てください:
2.2サービスファイル
一見、多くのファイルとディレクトリがありますが、実際には心配する必要はありません。 上記で見たものを扱い、プロジェクトファイルから始めます。
TARGET = DoNothing TEMPLATE = lib DEFINES += DONOTHING_LIBRARY # DoNothing files SOURCES += donothingplugin.cpp HEADERS += donothingplugin.h\ donothing_global.h\ donothingconstants.h OTHER_FILES = DoNothing.pluginspec # Qt Creator linking ## set the QTC_SOURCE environment variable to override the setting here QTCREATOR_SOURCES = $$(QTC_SOURCE) isEmpty(QTCREATOR_SOURCES):QTCREATOR_SOURCES=/home/kafeg/devel/Qt/qt-creator-2.4.0-src ## set the QTC_BUILD environment variable to override the setting here IDE_BUILD_TREE = $$(QTC_BUILD) isEmpty(IDE_BUILD_TREE):IDE_BUILD_TREE=/home/kafeg/devel/Qt/qt-creator-2.4.0-src/build ## uncomment to build plugin into user config directory ## <localappdata>/plugins/<ideversion> ## where <localappdata> is eg ## "%LOCALAPPDATA%\Nokia\qtcreator" on Windows Vista and later ## "$XDG_DATA_HOME/Nokia/qtcreator" or "~/.local/share/Nokia/qtcreator" on Linux ## "~/Library/Application Support/Nokia/Qt Creator" on Mac # USE_USER_DESTDIR = yes PROVIDER = DoNothingCompany include($$QTCREATOR_SOURCES/src/qtcreatorplugin.pri) include($$QTCREATOR_SOURCES/src/plugins/coreplugin/coreplugin.pri) LIBS += -L$$IDE_PLUGIN_PATH/Nokia
ご覧のとおり、この生成されたファイルには、プロジェクトの名前(DoNothing)とタイプ(ライブラリ)が記述され、3つのヘッダーファイルと1つのソースファイルが示され、pluginspecが示されています。 Qt Creatorソースの場所が示され、コメント付きの指示により、Qt Creatorディレクトリではなくアセンブルされたライブラリをインストールできますが、ローカルユーザーディレクトリには、ライブラリファイルの最終的な場所が依存するプロバイダが記述されます。 最後に、すべての拡張機能qtcreatorplugin.priおよびcoreplugin.priのベースファイルが含まれています。これらは、拡張機能と必要なすべてのライブラリとの正しいリンクを既に担当しています。
次のdonothing_global.hファイル:
#ifndef DONOTHING_GLOBAL_H #define DONOTHING_GLOBAL_H #include <QtCore/QtGlobal> #if defined(DONOTHING_LIBRARY) # define DONOTHINGSHARED_EXPORT Q_DECL_EXPORT #else # define DONOTHINGSHARED_EXPORT Q_DECL_IMPORT #endif #endif // DONOTHING_GLOBAL_H
およびdonothingconstants.h :
#ifndef DONOTHINGCONSTANTS_H #define DONOTHINGCONSTANTS_H namespace DoNothing { namespace Constants { const char * const ACTION_ID = "DoNothing.Action"; const char * const MENU_ID = "DoNothing.Menu"; } // namespace DoNothing } // namespace Constants #endif // DONOTHINGCONSTANTS_H
ここで、これ以上説明することなくすべてが明確になったと思います。 そして、明確ではないこと-将来このコードが必要になるのはいつになるかが明らかになります。 サービスファイルのリストは、DoNothing.pluginspec.inファイルで完成できます。
<plugin name=\"DoNothing\" version=\"0.0.1\" compatVersion=\"0.0.1\"> <vendor>DoNothingCompany</vendor> <copyright>(C) DoNothing Company</copyright> <license>DoNothing Company license text here</license> <description>DoNothing Company short description of plugin here</description> <url>http://www.donothing.com</url> <dependencyList> <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> </dependencyList> </plugin>
このファイルは、最終的にバイナリライブラリファイルとともに提供され、拡張機能の簡単な説明です。 そして、ここに彼が説明するものがあります:
- 拡張機能を実装するライブラリの名前で使用される拡張機能の名前。 (この例では、WindowsではDoNothing.dll、UnixではlibDoNothing.so)
- 拡張バージョン
- Qt Creatorの拡張バージョンが必要です
- ベンダー名
- 著作権
- ライセンステキスト
- 説明
- ベンダーURL
- この拡張機能が依存する拡張機能のリスト。
2.3拡張機能の実装
空のプロジェクトを正常にコンパイルするには、拡張機能の2つの主要な実装ファイルが必要です。 彼らはどんな人ですか? 主な要件は、メイン拡張クラスがIPlugin基本クラスから継承され、そのメソッドのいくつかをオーバーライドする必要があることです。
donothingplugin.h
#ifndef DONOTHING_H #define DONOTHING_H #include "donothing_global.h" #include <extensionsystem/iplugin.h> namespace DoNothing { namespace Internal { class DoNothingPlugin : public ExtensionSystem::IPlugin { Q_OBJECT public: DoNothingPlugin(); ~DoNothingPlugin(); bool initialize(const QStringList &arguments, QString *errorString); void extensionsInitialized(); ShutdownFlag aboutToShutdown(); private slots: void triggerAction(); }; } // namespace Internal } // namespace DoNothing #endif // DONOTHING_H
このコードの実装ファイルをさらに詳しく検討してください。
#include "donothingplugin.h" #include "donothingconstants.h" #include <coreplugin/icore.h> #include <coreplugin/icontext.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/actioncontainer.h> #include <coreplugin/coreconstants.h> #include <QtGui/QAction> #include <QtGui/QMessageBox> #include <QtGui/QMainWindow> #include <QtGui/QMenu> #include <QtCore/QtPlugin> using namespace DoNothing::Internal; DoNothingPlugin::DoNothingPlugin() { // Create your members } DoNothingPlugin::~DoNothingPlugin() { // Unregister objects from the plugin manager's object pool // Delete members }
コンストラクタとデストラクタは、ウィジェットやアクション(アクション)ではない基本変数を初期化するためにのみ使用されます。
bool DoNothingPlugin::initialize(const QStringList &arguments, QString *errorString) { // Register objects in the plugin manager's object pool // Load settings // Add actions to menus // connect to other plugins' signals // "In the initialize method, a plugin can be sure that the plugins it // depends on have initialized their members." Q_UNUSED(arguments) Q_UNUSED(errorString) Core::ActionManager *am = Core::ICore::instance()->actionManager(); QAction *action = new QAction(tr("DoNothing action"), this); Core::Command *cmd = am->registerAction(action, Constants::ACTION_ID, Core::Context(Core::Constants::C_GLOBAL)); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); Core::ActionContainer *menu = am->createMenu(Constants::MENU_ID); menu->menu()->setTitle(tr("DoNothing")); menu->addAction(cmd); am->actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); return true; }
initialize()関数は、Qt Creatorが拡張機能を初期化するときだと判断したときに呼び出されます。 この関数は、初期状態を初期化し、拡張機能に関連するすべてのアクションとオブジェクトをQt Creator自体に登録するように設計されています。
この拡張機能が依存するすべての拡張機能が既にメモリに読み込まれた後にのみ、関数が呼び出されます。 上記の例からわかるように、デフォルトのコードでは、新しいメニュー項目の追加がすでに説明されていますが、これについては少し後で説明します。
ここで知る必要があるのは、初期化が成功した場合、この関数はtrueを返し、失敗した場合はfalseを返し、エラーメッセージを人間の言語でerrorString変数に書き込むことです。
void DoNothingPlugin::extensionsInitialized() { // Retrieve objects from the plugin manager's object pool // "In the extensionsInitialized method, a plugin can be sure that all // plugins that depend on it are completely initialized." }
extensionsInitialized()メソッドは、初期化が完了した後に呼び出されます。 主に、電流に依存する拡張機能のアシスタントとして機能します。
ExtensionSystem::IPlugin::ShutdownFlag DoNothingPlugin::aboutToShutdown() { // Save settings // Disconnect from signals that are not needed during shutdown // Hide UI (if you add UI that is not in the main window directly) return SynchronousShutdown; }
aboutToShutdown()メソッドは、拡張機能がメモリからアンロードされる前に呼び出されます。
void DoNothingPlugin::triggerAction() { QMessageBox::information(Core::ICore::instance()->mainWindow(), tr("Action triggered"), tr("This is an action from DoNothing.")); } Q_EXPORT_PLUGIN2(DoNothing, DoNothingPlugin)
2.4拡張機能のビルドとテスト
拡張機能を構築するには、キーの組み合わせCtrl + Rを押すだけです。その後、拡張機能はアセンブルされ、Qt Ceator拡張機能ディレクトリにインストールされますが、Qt Creatorはこのライブラリを実行する方法を知らないため、起動しません。 この状況は、アプリケーションの起動設定ページ([プロジェクト]-> [起動]-> [起動構成]-> [プログラム])で修正できます。
その結果、Qt Creatorが起動し、拡張機能のリストに新しい行が表示されます:
いくつかのファイルを含む新しいディレクトリが、すべての拡張子のディレクトリに表示されました。
kafeg@kafeg-desktop:~/devel/Qt/qt-creator-2.4.0-src/build/lib/qtcreator/plugins/DoNothingCompany$ ls DoNothing.pluginspec libDoNothing.so
このようにして、Qt Creatorの最も基本的な拡張機能を追加できます。 続けましょう。
3新しいメニューとメニュー項目の追加
このパートでは、新しいメニュー項目を既存のメニューに追加する方法を学習し、独自のメニューを作成する方法も理解します。 しかし、最初に、Qt Creatorパネルメニューの内容を見てください。
パネルには、次のデフォルト要素が含まれています。
- ファイル
-作成
-開く
-最近のファイル
- 編集
-オプション
- ツール
- 窓
-出力パネル
- 助けて
デバッグ、アセンブリ、分析などの他のすべてのメニュー項目は、個別の拡張機能で実装されており、デフォルトのメニューセットの一部ではありません。
Qt開発者は、メニュー自体がQMenuクラスとQActionクラスの組み合わせによって実装され、QMenuBarクラスがそれらをパネルの形式で表示する責任があることを知っています。
3.1コア:: ActionManager
Qt Creatorの基本部分は、これは本質的に拡張機能をロードできる空のウィンドウです。 Qt Creatorが提供するすべての機能は、その拡張機能を通じて実装されます。 Qt Creatorの主な拡張機能は「コア」と呼ばれます。 この拡張機能がなければ、Qt Creatorはまったく何もありません。
コア拡張の主要コンポーネントの1つはActionManagerです。 ActionManagerは、すべてのメニュー、メニュー項目、およびキーボードショートカットの登録を担当するオブジェクトです。 実際、新しいメニュー項目を追加する場合は、ActionManagerオブジェクトを使用する必要があります。 少し下に、どのように...
ActionManagerオブジェクトにアクセスするには、コードに次のものが含まれている必要があります。
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/icore.h> ... Core::ActionManager* am = Core::ICore::instance()->actionManager();
3.2コア:: ActionContainer
ActionContianerは、Qt Creatorでメニューとメニューバーを提供します。 このクラスのインスタンスは直接作成されることはなく、メソッドActionManager :: createMenu()、ActionManager :: createMenuBar()などを介してアクセスされます。
デフォルトでは、すべてのメニューに関連付けられたActionContainerのインスタンスがあります。 ActionContainerのインスタンスを取得するには、次のコードを使用する必要があります。
#include <coreplugin/coreconstants.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/icore.h> Core::ActionManager* am = Core::ICore::instance()->actionManager(); Core::ActionContainer* ac = am->actionContainer( ID );
次の表に、ActionContainerインスタンスを受信できるデフォルトのIDを示します。 IDは、コア可視性スペースのconst char * static変数です。
メニュー | ID |
---|---|
ファイル | コア::定数:: M_FILE |
ファイル->新規 | コア::定数:: M_FILE_NEW |
ファイル->開く | コア::定数:: M_FILE_OPEN |
ファイル->最近のファイル | コア::定数:: M_FILE_RECENTFILES |
編集 | コア::定数:: M_EDIT |
編集->詳細 | コア::定数:: M_EDIT_ADVANCED |
道具 | コア::定数:: M_TOOLS |
窓 | コア::定数:: M_WINDOW |
ウィンドウペイン | コア::定数:: M_WINDOW_PANES |
助けて | コア::定数:: M_HELP |
たとえば、「ヘルプ」メニューへのポインターを取得する場合は、次のコードを使用する必要があります。
#include <coreplugin/coreconstants.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/icore.h> ... Core::ActionManager* am = Core::ICore::instance()->actionManager(); Core::ActionContainer* ac = am->actionContainer( Core::Constants::M_HELP );
3.3メニューとメニュー項目の追加
新しいメニュー項目を追加する方法を見てみましょう。 これを行うには、既存の関数initialize()に戻り、その実装をさらに詳しく見てみましょう。
bool DoNothingPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments) Q_UNUSED(errorString) Core::ActionManager *am = Core::ICore::instance()->actionManager(); QAction *action = new QAction(tr("DoNothing action"), this); Core::Command *cmd = am->registerAction(action, Constants::ACTION_ID, Core::Context(Core::Constants::C_GLOBAL)); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); Core::ActionContainer *menu = am->createMenu(Constants::MENU_ID); menu->menu()->setTitle(tr("DoNothing")); menu->addAction(cmd); am->actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); return true; }
ここに示されているコードは、はるかに理解しやすいものになっています。 そのため、ActionManagerへのポインターを取得してから、新しいメニュー項目を作成し、キーボードショートカットを割り当てます。 次に、独自のメニューを作成し、作成したアイテムを追加します。 また、定数ACTION_IDとMENU_IDが便利になったことにも注意してください。
次に、ActionContainerツールメニュー(M_TOOLS)へのポインターを取得し、メニューを追加します。
さらに、キーボードショートカットは、アプリケーションのすべてのキーボードショートカットのレジストリに入力され、その設定を変更できます。
また、独自のメニューをどこにでも追加できることに注意してください。 たとえば、メインメニューバーにメニューを追加する必要がある場合、M_TOOLS定数の代わりに、MENU_BAR定数を使用します。 また、メニューを別のメニュー内に配置するには、追加のパラメーターをaddMenu()関数に渡す必要があります
am->actionContainer(Core::Constants::MENU_BAR)->addMenu(am->actionContainer(Core::Constants::M_HELP), menu);
3.3メニュー項目イベントへの応答
メニュー項目はQActionクラスのインスタンスであるため、これらのオブジェクトから送信されるトリガー(bool)やトグル(bool)などの信号を使用し、スロットを作成してそれらに応答できます。 繰り返しますが、上記のコードから例を挙げることができます。
... connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); ... void DoNothingPlugin::triggerAction() { QMessageBox::information(Core::ICore::instance()->mainWindow(), tr("Action triggered"), tr("This is an action from DoNothing.")); }
4 Qt Creatorのアーキテクチャ
原則として、十分に大きい各システムには独自のアーキテクチャがあり、どのアーキテクチャを使用しているかを理解していれば、はるかに高速に進むことができます。 Qt Creatorはシンプルであり、このパートではその基本的なアーキテクチャを理解しようとします。その後、拡張機能の記述に引き続き取り組みます。
4.1 Core Qt Creator
Qt Creatorの中核は単なる拡張機能マネージャーです。 すべての機能はそれらを通して提供されます。
Qt Creatorの基本機能は、Core拡張機能(Core :: ICore)に実装されています。 前のパートでこの拡張機能については既に触れました。 次に、この基本拡張をコアと呼びます。 Extension Manager(ExtensionSystem :: PluginManager)は、一部の拡張機能が他の拡張機能に提供できるフックを介した拡張機能の相互作用のためのシンプルなオプションを提供します。
4.2拡張機能とは何ですか?
システムレベルでは、拡張機能は共有ライブラリです(WindowsではDLL、LinuxではSO、MacではDYLIB)。 開発者の観点から見ると、拡張機能は次のことを行うモジュールです。
- ExtensionSystem :: IPluginインターフェイスを継承および実装します。 さらに本文では、同様のクラスを「プラグインクラス」と呼びます。
- Q_EXPORT_PLUGINマクロを使用してプラグインクラスをエクスポートします。
- 拡張機能に関するメタデータを含む(プラグイン名).pluginspecファイルを提供します。
- 他の拡張機能が使用する可能性がある1つ以上のオブジェクトを提供します。
- 他の拡張機能によって提供される1つ以上のオブジェクトの可用性を確認します。
すでに最初の3つのポイントについては説明しましたが、最後の2つについてはどこも解決していません。
4.2.1使用可能なオブジェクトのリストを取得する方法
使用可能なオブジェクトは、PluginManager内のオブジェクトプールに保存されます。 PluginManagerのallObjects()メソッドは、オブジェクトのプール全体をQObjectへのポインターのリストとして返します。 以下は、利用可能なオブジェクトのリストを出力できるコードです。
#include <extensionsystem/pluginmanager.h> ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); QList<QObject*> objects = pm->allObjects(); QListWidget* listWidget = new QListWidget; Q_FOREACH(QObject* obj, objects) { QString objInfo = QString("%1 (%2)") .arg(obj->objectName()) .arg(obj->metaObject()->className()); listWidget->addItem(objInfo); } listWidget->show();
したがって、このセクションのコードを実行すると、利用可能なオブジェクトの長いリストが表示されます。
リスト内の名前から、オブジェクトはさまざまな拡張機能によって提供されていると結論付けることができます。 「提供されたオブジェクト」という用語をより正確に定義できるようになったと思います。
提供された(エクスポートされた)オブジェクトは、1つの拡張機能によって提供され、オブジェクトプールを通じて他の拡張機能で使用できるQObjectクラス(またはその子孫)のインスタンスです。
4.2.2使用可能なリストにオブジェクトをエクスポートする方法は?
この目的には3つの方法があります。
- IPlugin :: addAutoReleasedObject(QObject *)
- IPlugin :: addObject(QObject *)
- PluginManager :: addObject(QObject *)
IPlugin :: addObject()およびIPlugin :: addAutoReleasedObject()メソッドは、本質的にPluginManager :: addObject()メソッドを呼び出します。
IPluginメソッドは単に便宜上のものです。 拡張機能を使用してオブジェクトを追加することをお勧めします。 addAutoReleasedObject()メソッドとaddObject()メソッドの違いは、拡張機能が破棄されると、最初のメソッドで追加されたオブジェクトが自動的に破棄され、利用可能なオブジェクトのプールから(逆の順序で)削除されることです。 さらに、いつでもIPlugin :: removeObject(QObject *)メソッドを呼び出して、使用可能なプールからオブジェクトを手動で削除できます。
4.2.3エクスポートするオブジェクト
拡張機能は任意のオブジェクトを提供(エクスポート)できますが、通常、エクスポートされたオブジェクトは機能的な基礎に従って構成されます。 他のQt Creator機能は、エクスポートされたインターフェイスを介して提供されます。 それらのいくつかを次に示します。
- コア:: INavigationWidgetFactory
- コア:: IEditor
- コア:: IOptionsPage
- コア:: IOutputPane
- コア:: IWizard
C ++開発者は、クラスは通常インターフェイスと呼ばれ、そのすべてのメソッドは純粋に仮想でパブリックであるという事実に慣れています。 Qt Creatorでは、インターフェイスは1つ以上の純粋な仮想メソッドを持つQObjectの子孫です。
拡張機能にインターフェイスを実装するオブジェクトがある場合、そのようなオブジェクトをエクスポートする必要があります。 たとえば、拡張機能がINavigationWidgetFactoryインターフェイスの実装をエクスポートする場合、Coreはこの実装で作成されたウィジェットを自動的に選択して、ナビゲーションパネルに表示します。 例として、Core :: INavigationWidgetFactoryインターフェースの実装を介して、単純なQTableWidgetをナビゲーションバーに追加することを検討してください。
#include <coreplugin/inavigationwidgetfactory.h> #include <QTableWidget> class NavWidgetFactory : public Core::INavigationWidgetFactory { public: NavWidgetFactory() { } ~NavWidgetFactory() { } Core::NavigationView createWidget() { Core::NavigationView view; view.widget = new QTableWidget(50, 3); return view; } QString displayName() const { return "Spreadsheet"; } int priority() const { return 0; } QString id() const { return "Spreadsheet"; } }; bool DoNothingPlugin::initialize(const QStringList &arguments, QString *errorString) { ... // Provide a navigation widget factory. // Qt Creator's navigation widget will automatically // hook to our INavigationWidgetFactory implementation, which // is the NavWidgetFactory class, and show the QTableWidget // created by it in the navigation panel. addAutoReleasedObject(new NavWidgetFactory); return true; }
結果は次のとおりです。
4.2.4新しく輸出された施設の通知。
PluginManager :: addObject()メソッドが呼び出されると、PluginManagerはobjectAddedシグナル(QObject *)を送信します。 このシグナルを使用して、Qt Creatorの実行中にどのオブジェクトが新しく追加されたかを追跡できます。
明らかに、拡張機能はこの信号をスロットに接続した後にのみ処理できるため、完全な初期化後に追加されたオブジェクトに関する通知のみを受信します。
通常、この信号に接続されたスロットは、1つ以上のインターフェイスを監視します。たとえば、これは、INavigationWidgetFactoryインターフェイスを実装する新しいオブジェクトの外観に従うコードのように見える場合があります。
void Plugin::slotObjectAdded(QObject * obj) { INavigationWidgetFactory *factory = Aggregation::query<INavigationWidgetFactory>(obj); if(factory) { // use it here... } }
4.2.4オブジェクト検索
拡張機能は、特定の機能を提供するアプリケーション内のオブジェクトを見つける必要がある場合があります。これで、そのようなオブジェクトを検索する2つの方法がわかりました。
- PluginManager :: allObjects()メソッド。使用可能なすべてのオブジェクトのリストを返します。
- シグナルPluginManager :: objectAdded()に接続します。これにより、新しく追加されたオブジェクトに関する通知を受け取ることができます。
これらのメソッドを使用して、開発者はオブジェクトを追跡できます。しかし、オブジェクトを見つけるのはどうですか?これらの目的のために、PluginManager :: getObjects()メソッドがあります。たとえば、INavigationWidgetFactoryインターフェイスを実装するすべてのオブジェクトを検索する場合、次のコードを使用します。
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); QList<Core::INavigationWidgetFactory*> objects = pm->getObjects<Core::INavigationWidgetFactory>();
4.3オブジェクトの集約
集約の助けを借りて、複数の異なるQObjectを1つのオブジェクトに収集できます。Qt Creatorは通常、このアプローチを使用して複数のインターフェイスを組み合わせます。
#include <aggregation/aggregate.h> class Interface1 : public QObject { Q_OBJECT public: Interface1() { } ~Interface1() { } }; class Interface2 : public QObject { Q_OBJECT public: Interface2() { } ~Interface2() { } }; Aggregation::Aggregate bundle; bundle.add(new Interface1); bundle.add(new Interface2);
これで、バンドルオブジェクトには2つのオブジェクトへのポインターが含まれます。インターフェイスにアクセスするには、次のコードを使用できます。
Interface1* iface1Ptr = Aggregation::query<Interface1>( &bundle ); Interface2* iface2Ptr = Aggregation::query<Interface2>( &bundle );
1つのバンドルに複数のインターフェイスを含めることができます。
Aggregation::Aggregate bundle; bundle.add(new Interface1); bundle.add(new Interface2); bundle.add(new Interface1); bundle.add(new Interface1); QList<Interface1*> iface1Ptrs = Aggregation::query_all<Interface1>( &bundle );
また、追加されたインターフェースとバンドル自体の両方を削除します。
Aggregation::Aggregate* bundle = new Aggregation::Aggregate; bundle->add(new Interface1); bundle->add(new Interface2); Interface1* iface1Ptr = Aggregation::query<Interface1>(bundle); delete iface1Ptr; // deletes the bundle and all objects in it // same as delete bundle
オブジェクトAggregation :: Aggregateの説明がここで必要な理由は明らかではないかもしれませんが、以下の部分では、説明された例の実装と構造を簡素化するのにまだ役立ちます。
5新しいエディターの追加(エディター)
基本レベル(同じコアプラグイン)では、Qt Creatorはテキストエディターにすぎません。ただし、適切な拡張機能により、その機能は大幅に拡張されています。さまざまな言語の構文強調表示、C ++コードを使用したリファクタリングおよびナビゲーションツールなど、テキストエディタにさらに多くの機能が追加されています。UI(Qt Designer)、JS / QML、QRCリソースファイル、プロジェクトファイル(PRO / PRI)を編集するためのツールと、EXE / DLL / SOタイプのファイルを編集するための16進エディターがあります。
このパートでは、例としてHTML形式を使用して、独自のファイル形式用のエディターを作成する方法を見つけます。エディターでの作業が完了したら、HTMLファイルをエディターにアップロードして、何が起こるかを確認します。
5.1基本クラスとインターフェース
新しいエディターのサポートを追加するには、次のものが必要です。
- Core :: IEditorFactoryインターフェイスの実装をエクスポートするCore :: IPluginクラスを実装します。これは以前に学びました。
- Core :: IEditorFactoryインターフェイスを実装します。このインターフェイスを使用すると、渡されるMIMEタイプに応じて必要なエディターを作成できます。
- Core :: IEditorインターフェイスの実装を介して、ファイルエディター自体を実装します。この実装は、ファイルのタイプ(HTML、ODFなど)に応じてファイルを編集できるウィジェットを提供します。エディターは、現在編集/表示されているファイルにアクセスできる必要があります。
- Core :: IFileインターフェイスを実装します。これは、ハードドライブにファイルをロード/保存する作業に役立ちます。
次に、これらの各インターフェイスについて検討します。
5.1.1インターフェースコア:: IFile。
このインターフェイスは、ファイルの操作とユーザーインターフェイスの間の抽象的なレイヤーです。これは、ファイルのロード/保存、ファイル名の設定のための純粋に仮想的なメソッドを提供し、アプリケーションがファイルのMIMEタイプを判別し、特定のフラグの値を取得するのを支援します。このインターフェイスはsrc / plugins / coreplugin / ifile.hファイルで宣言されています:
質問が発生します-QFileが既に存在する場合、なぜIFileが必要なのですか?答えは次のとおりです。
- IFileは、ファイルをQByteArrayにロードするQFileとは異なり、データをCore :: IEditorに直接ロードします
- IFileは、ユーザーがエディターでファイルの編集を開始したときに、変更された()信号を送信できますが、コンテンツは変更されません。QFileは、ディスクの内容が変更された後にのみ、bytesWritten()を送信します。
- IFileは、ディスク上の別のファイルが別のプログラムによって変更されたかどうかを監視し、変更されている場合は、それをリロードすることを提案します。QFileと同様の機能。
5.1.2インターフェイスコア:: IEditor。
このインターフェイスの実装は、さまざまなファイルタイプのエディターを提供します。src / plugins / coreplugin / editormanager / ieditor.h
Coreで宣言:IEditorは主に以下へのアクセスを提供します。
- 編集ウィジェット(メソッドCore :: IEditor :: widget())。Qt Creatorが編集済みファイルの内容を表示するために使用します。
- Core :: IEditor :: file()メソッド。これはCore :: IFileへのポインタで、Qt Creatorはこれを使用してディスクを操作できます。
- エディターがアクティブになったときにQt Creatorが表示できるオプションのツールバー。
- ファイル内の現在のカーソル位置(Core :: IEditor :: currentLine()およびCore :: IEditor :: currentColumn())。
- 開いているファイルのリストに表示される名前、
下のスクリーンショットから、どこにあるかを確認できます。
5.1.3コア:: IEditorFactoryインターフェイス
このインターフェイスショーの実装は、サポートされているMIMEタイプのCore :: IEditorをインスタンス化するメソッドを提供します。src / plugins / coreplugin / editormanager / ieditorfactory.hの広告
IEditorFactory :: mimeType()メソッドは、エディターでサポートされているMIMEタイプを返します。IEditorFactory :: createEditor()メソッドは、特定のエディターを作成します。
5.1.4コア:: MimeDatabaseクラス
Core :: MimeDatabaseクラスには、Qt CreatorでサポートされているすべてのMIMEタイプが格納されています。特定のファイルのMIMEタイプを取得するのにも役立ちます。例:
#include <coreplugin/mimedatabase.h> Core::ICore* core = Core::ICore::instance(); Core::MimeDatabase* mdb = core->mimeDatabase(); Core::MimeType type1 = mdb->findByFile( QFileInfo("C:/Temp/sample.html") ); qDebug("File Type for sample.html = %s", qPrintable(type1.type())); Core::MimeType type2 = mdb->findByFile( QFileInfo("C:/Temp/TextEdit/Main.cpp") ); qDebug("File Type for Main.cpp = %s", qPrintable(type2.type())); Core::MimeType type3 = mdb->findByFile( QFileInfo("C:/Temp/TextEdit/TextEdit.pro") ); qDebug("File Type for TextEdit.pro = %s", qPrintable(type3.type()));
そして結論:
File Type for sample.html = text/plain File Type for Main.cpp = text/x-c++src File Type for TextEdit.pro = text/plain
動作するために、Core :: MimeDatabaseはファイルサフィックス、パターン、およびその他の魔法のアクションを使用して、何らかの方法でファイルのMIMEタイプを取得します。例を使用して、MIMEタイプ別にファイルを開く手順を見てみましょう。
- ユーザーがファイルを開きます([ファイル]-> [開く])。
- Qt CreatorはCore :: MimeDatabaseを使用して、選択したファイルのMIMEタイプを決定します。
- Qt Creatorは、すべてのCore :: IEditorFactoryのMIMEタイプをスキャンします。
- Qt Creatorは、見つかったCore :: IEditorFactoryにCore :: IEditorのインスタンスを作成するように要求します。
- Core :: IEditor :: widget()によって返されるウィジェットがワークスペースに表示されます。
- メソッドCore :: IEditor :: open()は、最初のステップで選択されたファイル名で呼び出されます。
5.1.5新しいMIMEタイプの追加
新しいエディターのサポートを追加する場合は、新しいエディターでサポートされているMIMEタイプをCore :: MimeDatabaseに登録する必要があります。これを行うにはいくつかの方法がありますが、ここではXMLファイルを作成することで最も簡単な方法を見ていきます。たとえば、text / html mimeタイプを登録し、* .htmlファイルに関連付けたいとします。XMLファイルを作成し、text-html-mimetype.xmlとして保存します。
<?xml version="1.0" encoding="UTF-8"?> <mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> <mime-type type="text/html"> <sub-class-of type="text/plain"/> <comment>HTML File</comment> <glob pattern="*.html"/> </mime-type> </mime-info>
これで、コア:: MimeDatabase :: addMimeTypes()メソッドを使用して、このMIMEタイプを登録できます。
Core::ICore* core = Core::ICore::instance(); Core::MimeDatabase* mdb = core->mimeDatabase(); QString errMsg; bool success = mdb->addMimeTypes("text-html-mimetype.xml", errMsg);
これを行うとすぐに、Qt Creatorはすぐにすべての* .htmlファイルをMIMEタイプtext / htmlに関連付け始めました。
5.2 Qt Creator HTMLエディターを拡張します。
さて、理論が少し止まったので、HTMLファイルの表示/編集をサポートするエディターの作成を開始できます。計画を実装するには、いくつかのクラスを作成する必要があります。
クラス | 基本クラス | 説明 |
HtmlEditorWidget | QTabWidget | これは、2つのタブを持つウィジェットになります。最初のタブには最終結果が表示され、2番目のタブにはドキュメントのソースが表示されます。 |
Htmlfile | コア:: IFile | HtmlEditorWidgetのIFileインターフェイスの実装。 |
Htmleditor | コア:: IEditor | HtmlEditorWidgetおよびHtmlFileとの相互作用を制御するIEditorを実装します。 |
HtmlEditorFactory | コア:: IEditorFactory | IEditorFactoryを実装して、MIMEタイプ「text / html」に基づいてIEditorのインスタンスを作成します。 |
HtmlEditorPlugin | コア:: IPlugin | 上記のすべてをQt Creatorと通信するためのIPluginを実装します。 |
そこで、Qt Creatorモジュールの新しいプロジェクトを作成し、たとえばHTMLEditorと呼び、読み進めます。
5.2.1 HTML Editorウィジェットの実装
デフォルトでは、Qt Creatorはシンプルなテキストエディターを使用してHTMLファイルを表示します。1つのタブでページを表示でき、もう1つのタブで編集できる2タブエディターを作成しています。
#ifndef HTMLEDITORWIDGET_H #define HTMLEDITORWIDGET_H #include <QTabWidget> #include <QWebView> #include <QPlainTextEdit> struct HtmlEditorWidgetData { QWebView *webView; QPlainTextEdit *textEdit; bool modified; QString path; }; class HtmlEditorWidget : public QTabWidget { Q_OBJECT public: HtmlEditorWidget(QWidget* parent = 0); ~HtmlEditorWidget(); void setContent(const QByteArray& ba, const QString& path=QString()); QByteArray content() const; QString title() const; protected slots: void slotCurrentTabChanged(int tab); void slotContentModified(); signals: void contentModified(); void titleChanged(const QString&); private: HtmlEditorWidgetData* d; }; #endif // HTMLEDITORWIDGET_H
デザイナーは2つのQWebViewウィジェットとQPlainTextEditウィジェットを作成し、それらを現在のウィジェットにタブとして追加し、3つの接続を作成します。
- ユーザーがソースの編集から表示に移動すると、QWeBViewのコンテンツが更新されます
- ユーザーがコンテンツを変更すると、信号を送信する必要があります
- 最後に、QWebViewヘッダーの変更を監視する必要があります。
#include "htmleditorwidget.h" HtmlEditorWidget::HtmlEditorWidget(QWidget* parent) :QTabWidget(parent) { d = new HtmlEditorWidgetData; d->webView = new QWebView; d->textEdit = new QPlainTextEdit; addTab(d->webView, "Preview"); addTab(d->textEdit, "Source"); //setTabPosition(QTabWidget::South); setTabShape(QTabWidget::Triangular); d->textEdit->setFont( QFont("Courier", 12) ); connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentTabChanged(int))); connect(d->textEdit, SIGNAL(textChanged()), this, SLOT(slotContentModified())); connect(d->webView, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString))); d->modified = false; }
デストラクタはプライベートオブジェクトのみを削除します。
HtmlEditorWidget::~HtmlEditorWidget() { delete d; }
setContent()メソッドは、webViewとtextEditのコンテンツを設定します。そしてcontent()メソッドはそれに応じてコンテンツを返します。title()メソッドは、開いているファイルのリストに表示される文字列を返します。さて、最後の2つのメソッドは、コンストラクターで作成された信号接続を処理します。
void HtmlEditorWidget::setContent(const QByteArray& ba, const QString& path) { if(path.isEmpty()) d->webView->setHtml(ba); else d->webView->setHtml("file:///" + path); d->textEdit->setPlainText(ba); d->modified = false; d->path = path; } QByteArray HtmlEditorWidget::content() const { QString htmlText = d->textEdit->toPlainText(); return htmlText.toAscii(); } QString HtmlEditorWidget::title() const { return d->webView->title(); } void HtmlEditorWidget::slotCurrentTabChanged(int tab) { if(tab == 0 && d->modified) setContent( content(), d->path ); } void HtmlEditorWidget::slotContentModified() { d->modified = true; emit contentModified(); }
5.2.2コア:: IFileの実装
このインターフェイスをHtmlFileクラスに実装します。このクラスは、Core :: IFileの複数の仮想メソッドを実装し、編集中のドキュメントのステータスを反映するように修正済みフラグを設定できます。
#ifndef HTMLFILE_H #define HTMLFILE_H #include <coreplugin/ifile.h> #include "htmleditorconstants.h" struct HtmlFileData; class HtmlEditor; class HtmlEditorWidget; class HtmlFile : public Core::IFile { Q_OBJECT public: HtmlFile(HtmlEditor* editor, HtmlEditorWidget* editorWidget); ~HtmlFile(); void setModified(bool val=true); bool isModified() const; QString mimeType() const; bool save(QString *errorString, const QString &fileName, bool autoSave); bool reload(QString *errorString, ReloadFlag flag, ChangeType type); void rename(const QString &newName); bool open(const QString &fileName); void setFilename(const QString& filename); QString fileName() const; QString defaultPath() const; QString suggestedFileName() const; QString fileFilter() const; QString fileExtension() const; bool isReadOnly() const; bool isSaveAsAllowed() const; void modified(ReloadBehavior* behavior); protected slots: void modified() { setModified(true); } private: HtmlFileData* d; }; struct HtmlFileData { HtmlFileData() : mimeType(HTMLEditor::Constants::C_HTMLEDITOR_MIMETYPE), editorWidget(0), editor(0), modified(false) { } const QString mimeType; HtmlEditorWidget* editorWidget; HtmlEditor* editor; QString fileName; bool modified; }; #endif // HTMLFILE_H
コンストラクターで、必要な関連付けを公開するだけです。デストラクタで、プライベートオブジェクトを削除します。
#include "htmlfile.h" #include <QFile> #include <QFileInfo> #include "htmleditor.h" #include "htmleditorwidget.h" HtmlFile::HtmlFile(HtmlEditor* editor, HtmlEditorWidget* editorWidget) : Core::IFile(editor) { d = new HtmlFileData; d->editor = editor; d->editorWidget = editorWidget; } HtmlFile::~HtmlFile() { delete d; }
setModified()メソッドは変更されたフラグを設定し、変更された()シグナルを送信します
void HtmlFile::setModified(bool val) { if(d->modified == val) return; d->modified = val; emit changed(); } bool HtmlFile::isModified() const { return d->modified; }
ここから、このクラスのMIMEタイプを返します。
QString HtmlFile::mimeType() const { return d->mimeType; }
save()メソッドは、File-> Saveメニュー項目が選択されたとき、またはCtrl + Sキーの組み合わせによって呼び出されます。HtmlEditorWidgetのコンテンツ(textEditから)を現在の関連ファイルに保存します。変更されたフラグはfalseに設定されます。
bool HtmlFile::save(const QString &fileName) { QFile file(fileName); if(file.open(QFile::WriteOnly)) { d->fileName = fileName; QByteArray content = d->editorWidget->content(); file.write(content); setModified(false); return true; } return false; }
[ファイル]-> [開く]を選択すると、open()メソッドが呼び出されます。Ctrl + Oのいずれか ファイルをロードし、編集ウィジェットのsetContent()関数に渡します。
bool HtmlFile::open(const QString &fileName) { QFile file(fileName); if(file.open(QFile::ReadOnly)) { d->fileName = fileName; QString path = QFileInfo(fileName).absolutePath(); d->editorWidget->setContent(file.readAll(), path); d->editor->setDisplayName(d->editorWidget->title()); return true; } return false; } bool HtmlFile::reload(QString *errorString, ReloadFlag flag, ChangeType type) { return open(d->fileName); } void HtmlFile::rename(const QString &newName) { QFile file(d->fileName); file.rename(newName); setFilename(newName); } void HtmlFile::setFilename(const QString& filename) { d->fileName = filename; } QString HtmlFile::fileName() const { return d->fileName; } QString HtmlFile::defaultPath() const { return QString(); } QString HtmlFile::suggestedFileName() const { return QString(); } QString HtmlFile::fileFilter() const { return QString(); } QString HtmlFile::fileExtension() const { return QString(); } bool HtmlFile::isReadOnly() const { return false; } bool HtmlFile::isSaveAsAllowed() const { return true; } void HtmlFile::modified(ReloadBehavior* behavior) { Q_UNUSED(behavior); }
5.2.3コア:: IEditorの実装
Qt Creatorがhtmlエディターウィジェットを使用してHtmlFileに関連付ける機能を提供するために、IEditorを実装しています。
#ifndef HTMLEDITOR_H #define HTMLEDITOR_H #include <coreplugin/editormanager/ieditor.h> #include <QToolBar> struct HtmlEditorData; class HtmlFile; class HtmlEditorWidget; class HtmlEditor : public Core::IEditor { Q_OBJECT public: HtmlEditor(HtmlEditorWidget* editorWidget); ~HtmlEditor(); bool createNew(const QString& /*contents*/ = QString()); QString displayName() const; 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); QToolBar* toolBar(); // From Core::IContext QWidget* widget(); Core::Context context() const; QString id() const; protected slots: void slotTitleChanged(const QString& title) { setDisplayName(title); } private: HtmlEditorData* d; };
HtmlEditorDataオブジェクトには、HtmlEditorWidgetおよびHtmlFileオブジェクトへのポインターが格納され、displayName変数は、ユーザーに表示されるエディターの名前を格納するために使用されます。
struct HtmlEditorData { HtmlEditorData() : editorWidget(0), file(0) { } HtmlEditorWidget* editorWidget; QString displayName; HtmlFile* file; Core::Context context; }; #endif // HTMLEDITOR_H
コンストラクターは自身を初期化し、HtmlFileのインスタンスを作成し、3つすべてのオブジェクト間の関連付けを付加します。デストラクタは、伝統的に、プライベートオブジェクトのみを削除します。
#include "htmleditor.h" #include "htmlfile.h" #include "htmleditorwidget.h" HtmlEditor::HtmlEditor(HtmlEditorWidget* editorWidget) : Core::IEditor(editorWidget) { d = new HtmlEditorData; d->editorWidget = editorWidget; d->file = new HtmlFile(this, editorWidget); //Core::UniqueIDManager* uidm = Core::UniqueIDManager::instance(); d->context = *(new Core::Context(HTMLEditor::Constants::C_HTMLEDITOR)); //<< uidm->uniqueIdentifier(HTMLEditor::Constants::C_HTMLEDITOR); connect(d->editorWidget, SIGNAL(contentModified()), d->file, SLOT(modified())); connect(d->editorWidget, SIGNAL(titleChanged(QString)), this, SLOT(slotTitleChanged(QString))); connect(d->editorWidget, SIGNAL(contentModified()), this, SIGNAL(changed())); } HtmlEditor::~HtmlEditor() { delete d; }
マッピング用の3つの単純な関数。
QWidget* HtmlEditor::widget() { return d->editorWidget; } Core::Context HtmlEditor::context() const { return d->context; } Core::IFile* HtmlEditor::file() { return d->file; }
createNew()メソッドは、HtmlEditorWidgetとHtmlFileのコンテンツをリセットします。
bool HtmlEditor::createNew(const QString& contents) { Q_UNUSED(contents); d->editorWidget->setContent(QByteArray()); d->file->setFilename(QString()); return true; }
open()メソッドは、HtmlFileで開くファイル名を渡します。
bool HtmlEditor::open(const QString &fileName) { return d->file->open(fileName); }
エディターのタイプを返します。
const char* HtmlEditor::kind() const { return HTMLEditor::Constants::C_HTMLEDITOR; }
displayNameは、ComboBoxでファイル名を表示するために使用されます。
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; } QToolBar* HtmlEditor::toolBar() { return 0; } bool HtmlEditor::isTemporary() const { return false; } QString HtmlEditor::id() const { return QString(); }
5.2.4コアの実装:: IEditorFactory
HtmlEditorFactoryクラスは、Core :: IEditorFactoryインターフェイスを実装します。
#ifndef HTMLEDITORFACTORY_H #define HTMLEDITORFACTORY_H #include <coreplugin/editormanager/ieditorfactory.h> #include <QStringList> #include "htmleditorplugin.h" struct HtmlEditorFactoryData; class HtmlEditorFactory : public Core::IEditorFactory { Q_OBJECT public: HtmlEditorFactory(HTMLEditor::Internal::HTMLEditorPlugin* owner); ~HtmlEditorFactory(); QStringList mimeTypes() const; QString kind() const; Core::IEditor* createEditor(QWidget* parent); Core::IFile* open(const QString &fileName); private: HtmlEditorFactoryData* d; }; #endif // HTMLEDITORFACTORY_H
HtmlEditorFactoryData構造には、HtmlEditorFactoryクラスのプライベートデータが含まれています。この構造のコンストラクターは、HTMLEditor :: Constants :: C_HTMLEDITOR_MIMETYPEに含まれるMIMEタイプで初期化します。また、値HTMLEditor :: Constants :: C_HTMLEDITORでエディタータイプを初期化します。すべての定数は、htmleditorconstants.hファイルで宣言されています。
#include "htmleditorfactory.h" #include "htmleditorconstants.h" #include <coreplugin/editormanager/editormanager.h> #include "htmleditorwidget.h" #include <QStringList> #include <coreplugin/editormanager/ieditor.h> #include "htmleditor.h" struct HtmlEditorFactoryData { HtmlEditorFactoryData() : kind(HTMLEditor::Constants::C_HTMLEDITOR) { mimeTypes << QString(HTMLEditor::Constants::C_HTMLEDITOR_MIMETYPE); } QString kind; QStringList mimeTypes; };
次に、簡単な使い慣れたメソッドのドロップ。
HtmlEditorFactory::HtmlEditorFactory(HTMLEditor::Internal::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; }
open()メソッドはファイル名をエディターマネージャーに渡し、エディターマネージャーは新しいエディターを作成して開くか、既存のエディターのいずれかを開きます。
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); }
5.2.5メイン拡張クラス
2番目のパートで得た知識を使用して、HtmlEditorPluginクラスを実装します。真実は、initialize()メソッドを少し変更することです。
bool HTMLEditorPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments) Q_UNUSED(errorString) Core::ICore* core = Core::ICore::instance(); Core::MimeDatabase* mdb = core->mimeDatabase(); QString *errMsg = new QString(); if(!mdb->addMimeTypes(":/text-html-mimetype.xml", errMsg)) return false; addAutoReleasedObject(new HtmlEditorFactory(this)); return true; }
6サイドナビゲーションバーの追加
Qt Creatorのナビゲーションバーは、次のようなコンポーネントを含む領域です。
- プロジェクト
- ドキュメントを開く
- しおり
- ファイルシステム
- クラス概要
- 復習
- 型階層
- その他...
さらに、1つではなく複数のナビゲーションパネルを同時に使用できます。
前の部分のいずれかにラベルを含むナビゲーションバーを追加しようとしたことを覚えていますか?ここで、ほぼ同じことを行いますが、タスクを少し複雑にします。
6.1コア:: INavigationWidgetFactory
したがって、覚えている限り、新しいナビゲーションバーを追加するには、ファイルplugins / corelib / inavigationwidgetfactory.hにあるCore :: INavigationWidgetFactoryインターフェイスの独自の実装を作成する必要があります。
6.2パネル用のウィジェットの準備
Qt Creatorモジュールプロジェクトを再作成します。そして、それをFTPBrowserと呼びます。はい、元の文書にこの例があったからこそです。また、このリンクを見て、FtpDirModelクラスをダウンロードする必要があります。
プロジェクトで新しいフォームクラスを作成し、フォームをこのフォームに移動します:
ユーザーがFTPパス行にFTPディレクトリへのパスを入力して[Go]をクリックすると、このFTPのコンテンツがすぐ下のQTreeViewにアップロードされます。たとえば、このウィジェットにFTPBrowserFormという名前を付けました。フォームのソースは提供しませんが、他のすべてと一緒に取得できます。インターフェースの実装にすぐに進みます。
#include <coreplugin/inavigationwidgetfactory.h> class FtpViewNavigationWidgetFactory : public Core::INavigationWidgetFactory { public: FtpViewNavigationWidgetFactory() { } ~FtpViewNavigationWidgetFactory() { } Core::NavigationView createWidget(); QString displayName() const { return "FTP View"; } int priority() const { return 0; } QString id() const { return "Spreadsheet"; } };
createWidget()メソッドは、新しいウィジェットのみを作成し、それへのポインターを返します。displayName()メソッドは、ユーザーに表示する文字列を返します。
Core::NavigationView FtpViewNavigationWidgetFactory::createWidget() { Core::NavigationView view; view.widget = new FTPBrowserForm; return view; }
取得したものは次のとおりです。
6.3パネルの保存と復元
Qt Creatorを再起動した後、パネルの状態を保存/ロードする必要がある場合があります。これらの目的のために、INavigationWidgetFactoryインターフェースには2つの特別な仮想関数があります。
void saveSettings(int position, QWidget *widget); void restoreSettings(int position, QWidget *widget);
これらの2つのメソッドをオーバーライドすることにより、ウィジェットの状態を簡単に制御できます。コードの小さな例を次に示します。
void FtpViewNavigationWidgetFactory::saveSettings(int position, QWidget *widget) { FTPBrowserForm* ftpExp = qobject_cast<FTPBrowserForm*>(widget); if(!ftpExp) return; QSettings *settings = Core::ICore::instance()->settings(); settings->setValue("FtpView.URL", ftpExp->url().toString()); } void FtpViewNavigationWidgetFactory::restoreSettings(int position, QWidget *widget) { FTPBrowserForm* ftpExp = qobject_cast<FTPBrowserForm*>(widget); if(!ftpExp) return; QSettings *settings = Core::ICore::instance()->settings(); QString urlStr = settings->value("FtpView.URL").toString(); ftpExp->setUrl( QUrl(urlStr) ); }
パラメーターが位置とパネルウィジェットへのポインターである2つの単純な関数。
Fuf ...それは今のところすべてです...記事の残りの部分は公開されます...それがいつ追加されるかは=)