Warning, /frameworks/ktexteditor/docs/plugin_hosting.dox is written in an unsupported language. File is not indexed.
0001 /** \page kte_plugin_hosting Hosting KTextEditor plugins 0002 0003 While the KTextEditor framework provides a powerful text editor in itself, 0004 further features are available from plugins (KTextEditor::Plugin). At the time of this writing, 0005 all known KTextEditor plugins are maintained by the kate project, but most 0006 can be used in other hosting applications, as well. 0007 0008 This page is about supporting KTextEditor plugins in your application. For information on 0009 developing the plugins themselves, refer to KTextEditor::Plugin. 0010 0011 \section kte_basic_plugin_loading Loading simple plugins 0012 The steps needed to find and load basic KTextEditor plugins are roughly as follows: 0013 0014 \code 0015 QStringList plugins_to_load = QStringList() << "openlinkplugin" << "rainbowparens"; 0016 QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("ktexteditor")); 0017 for (const auto &plugin_meta_data : plugins) { 0018 QString identifier = plugin_meta_data.filename().basename(); 0019 if (!plugins_to_load.contains(identifier)) { 0020 continue; 0021 } 0022 plugins_to_load.removeOne(identifier); // avoid loading separate versions of the same plugin 0023 0024 KTextEditor::Plugin *plugin = KPluginFactory::instantiatePlugin<KTextEditor::Plugin>(plugin_meta_data, this, QVariantList() << identifier).plugin; 0025 if (plugin) { 0026 emit KTextEditor::Editor::instance()->application()->pluginCreated(identifier, plugin); 0027 QObject* created = plugin->createView(); 0028 if (created) { 0029 emit mainWindow()->main->pluginViewCreated(identifier, created); 0030 KTextEditor::SessionConfigInterface *interface = qobject_cast<KTextEditor::SessionConfigInterface *>(created); 0031 if (interface) { 0032 // NOTE: Some plugins will misbehave, unless readSessionConfig has been called! 0033 KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin:%1:").arg(identifier)); 0034 interface->readSessionConfig(group); 0035 } 0036 } 0037 } 0038 } 0039 \endcode 0040 0041 Note, however, that only a few basic plugins will actually be functional with the above, alone. 0042 For others, we need to implement several additional functions, as detailed, below. 0043 0044 \section kte_full_plugin_hosting Implementing full plugin hosting 0045 I order to allow plugins to interact with the hosting application (e.g. creating or activating additional windows/widgets), 0046 you need to implement two interfacing classes: 0047 - KTextEditor::Application (singleton) 0048 - KTextEditor::MainWindow 0049 0050 The latter corresponds to top level windows in your application (it's ok, if your application only supports a single 0051 toplevel window), with the assumption being that several document- and/or tool-windows can existing in each main window. 0052 0053 The two classes are really just a thin layer to dispatch from API to be used in plugins to the appropiate 0054 functionality in your application. For best runtime compatibility even across different version of KTextEditor, this is 0055 implemented using Qt slots. E.g. KTextEditor::MainWindow::activeView() is defined as: 0056 0057 \code 0058 KTextEditor::View *MainWindow::activeView() 0059 { 0060 // dispatch to parent 0061 KTextEditor::View *view = nullptr; 0062 QMetaObject::invokeMethod(parent(), "activeView", Qt::DirectConnection, Q_RETURN_ARG(KTextEditor::View*, view)); 0063 return view; 0064 } 0065 \endcode 0066 0067 I.e. this function (and most others in KTextEditor::MainWindow and KTextEditor::Application) simply invokes 0068 a slot by the same name and signature in its parent QObject. This is what you need to provide. The following example should 0069 illustrate the idea: 0070 0071 \code 0072 class MyKTEMainWindow : public QObject() { 0073 MyKTEMainWindow() { 0074 // create a dispatch object _as a child of this object_ 0075 kte_win = new KTextEditor::MainWindow(this); 0076 } 0077 [...] 0078 public slots: 0079 KTextEditor::View* activateView(KTextEditor::Document *document) { 0080 auto view = myFindViewForDoc(document); 0081 myActivateView(view); 0082 return view; 0083 } 0084 [further implementations] 0085 private: 0086 friend class MyKTEApplication; 0087 KTextEditor::MainWindow* kte_win; 0088 } 0089 0090 class MyKTEApplication : public QObject() { 0091 MyKTEApplicaiton() { 0092 // create a dispatch object _as a child of this object_ 0093 kte_app = new KTextEditor::Application(this); 0094 // For simplicity, let's assume a single main window, and create a wrapper for it, here 0095 my_main_win = new MyKTEMainWindow; 0096 0097 // register with KTextEditor 0098 KTextEditor::Editor::instance()->setApplication(kte_app); 0099 } 0100 [...] 0101 public slots: 0102 KTextEditor::MainWindow* activeMainWindow() { 0103 return my_main_win->kte_win; 0104 } 0105 [further implementations] 0106 private: 0107 KTextEditor::Application* kte_app; 0108 MyKTEMainWindow* my_main_win; 0109 } 0110 \endcode 0111 0112 @note Due to the lose coupling via Qt slots, you may not need to implement a dispatch slots for every 0113 single member in KTextEditor::Application, and KTextEditor::MainWindow. Naturally, however, plugins will be 0114 more likely to work as expected, the more complete the hosting app implements these interfaces. 0115 0116 @note Don't forget to integrate the plugin config pages, if desired: @see KTextEditor::Plugin::configPage(), @see KTextEditor::Plugin::configPages(). 0117 0118 \see KTextEditor::Plugin, KTextEditor::Application, KTextEditor::MainWindow 0119 0120 */