Neverendingo (Talk | contribs) m (Text replace - "<code xml>" to "<syntaxhighlight lang="xml">") |
|||
| Line 61: | Line 61: | ||
'''timedateui.rc''' | '''timedateui.rc''' | ||
| − | < | + | <syntaxhighlight lang="xml"> |
<!DOCTYPE kpartgui> | <!DOCTYPE kpartgui> | ||
<kpartplugin name="ktexteditor_timedate" library="ktexteditor_timedate" version="2"> | <kpartplugin name="ktexteditor_timedate" library="ktexteditor_timedate" version="2"> | ||
| Tutorial Series | Kate Plugin Tutorial |
| Previous | C++, Qt, KDE development environment |
| What's Next | Add a configuration dialog for it |
| Further Reading | CMake, The actual plugin code |
Contents |
We are going to create a dummy plugin for Kate in this tutorial. Our plugin will be able to insert current Date & Time. For now, our plugin will add on the cursor position on the active document the next information:
On the next chapter we will learn how to customize this output string creating a configuration dialog for this plugin.
Every plugin needs a .desktop file that describes it.
ktexteditor_timedate.desktop
[Desktop Entry]
Encoding=UTF-8
X-KDE-Library=ktexteditor_timedate
X-KDE-PluginInfo-Author=Konqui the Dragon
X-KDE-PluginInfo-Email=konqui@kde.org
X-KDE-PluginInfo-Name=ktexteditortimedate
X-KDE-PluginInfo-Version=0.1
X-KDE-PluginInfo-Website=http://kate.kde.org
X-KDE-PluginInfo-Category=Editor
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=false
X-KDE-ParentApp=kate
X-KDE-Version=4.0
ServiceTypes=KTextEditor/Plugin
Type=Service
Icon=korganizer
Name=Time & Date
Comment=Insert current Time & Date
There are important parts on this file:
This file is the one that will let our plugin merge with the Kate environment (toolbars and/or menubars). In this case when our plugin is loaded this file tells the KDE XML classes that it will add a separator, and that there is an action named "tools_insert_timedate". We will need to interact with this action later.
timedateui.rc
<!DOCTYPE kpartgui> <kpartplugin name="ktexteditor_timedate" library="ktexteditor_timedate" version="2"> <MenuBar> <Menu name="tools"><Text>&Tools</Text> <separator group="tools_operations" /> <Action name="tools_insert_timedate" group="tools_operations"/> </Menu> </MenuBar> </kpartplugin> </code> === The header file === '''timedate.h''' <code cppqt> // Avoid multiple header inclusion #ifndef TIMEDATE_H #define TIMEDATE_H // Include the basics #include <ktexteditor/plugin.h> #include <ktexteditor/view.h> #include <kxmlguiclient.h> #include <klocalizedstring.h> #include <QtCore/QEvent> #include <QtCore/QObject> #include <QtCore/QList> /** * This is the plugin class. There will be only one instance of this class. * We always want to inherit KTextEditor::Plugin here. */ class TimeDatePlugin : public KTextEditor::Plugin { public: // Constructor explicit TimeDatePlugin(QObject *parent, const QVariantList &args); // Destructor virtual ~TimeDatePlugin(); // Overriden methods // This method is called when a plugin has to be added to a view. As there // is only one instance of this plugin, but it is possible for plugins to // behave in different ways in different opened views where it is loaded, in // Kate plugins are added to views. For that reason we have the plugin itself // (this class) and then the plugin view class. // In this methods we have to create/remove TimeDatePluginView classes. void addView (KTextEditor::View *view); void removeView (KTextEditor::View *view); void readConfig(); void writeConfig(); private: QList<class TimeDatePluginView*> m_views; }; /** * This is the plugin view class. There can be as much instances as views exist. */ class TimeDatePluginView : public QObject, public KXMLGUIClient { Q_OBJECT public: explicit TimeDatePluginView(KTextEditor::View *view = 0); ~TimeDatePluginView(); private Q_SLOTS: void slotInsertTimeDate(); private: KTextEditor::View *m_view; }; #endif // TIMEDATE_H </code> === The source file === '''timedate.cpp''' <code cppqt> // Own includes #include "timedate.h" // Include the basics #include <ktexteditor/document.h> #include <kpluginfactory.h> #include <kpluginloader.h> #include <klocale.h> #include <kaction.h> #include <kactioncollection.h> #include <kdatetime.h> // This macro defines a KPluginFactory subclass named TimeDatePluginFactory. The second // argument to the macro is code that is inserted into the constructor of the class. // I our case all we need to do is register one plugin. If you want to have more // than one plugin in the same library then you can register multiple plugin classes // here. The registerPlugin function takes an optional QString parameter which is a // keyword to uniquely identify the plugin then (it maps to X-KDE-PluginKeyword in the // .desktop file). K_PLUGIN_FACTORY(TimeDatePluginFactory, registerPlugin<TimeDatePlugin>(); ) // With the next macro call, the library exports version information about the // Qt and KDE libraries being used and (most important) the entry symbol to get at // the factory we defined above. // The argument this macro takes is the constructor call of the above factory which // provides two constructors. One which takes a KAboutData* and another one // that takes two (optional) const char* parameters (Same as for KComponentData // constructors). // We put there the X-KDE-LibraryName. // Is important to provide as last parameter "ktexteditor_plugins". K_EXPORT_PLUGIN(TimeDatePluginFactory("ktexteditor_timedate", "ktexteditor_plugins")) // Constructor TimeDatePlugin::TimeDatePlugin(QObject *parent, const QVariantList &args) : KTextEditor::Plugin(parent) { // Avoid warning on compile time because of unused argument Q_UNUSED(args); } // Destructor TimeDatePlugin::~TimeDatePlugin() { } // Create the plugin view class and add it to the views list void TimeDatePlugin::addView(KTextEditor::View *view) { TimeDatePluginView *nview = new TimeDatePluginView(view); m_views.append(nview); } // Find the view where we want to remove the plugin from, and remove it. // Do not forget to free the memory. void TimeDatePlugin::removeView(KTextEditor::View *view) { for (int z = 0; z < m_views.size(); z++) { if (m_views.at(z)->parentClient() == view) { TimeDatePluginView *nview = m_views.at(z); m_views.removeAll(nview); delete nview; } } } // We do nothing on this methods since our plugin is not configurable yet void TimeDatePlugin::readConfig() { } void TimeDatePlugin::writeConfig() { } // Plugin view class TimeDatePluginView::TimeDatePluginView(KTextEditor::View *view) : QObject(view) , KXMLGUIClient(view) , m_view(view) { setComponentData(TimeDatePluginFactory::componentData()); KAction *action = new KAction(i18n("Insert Time && Date"), this); // Here we need as first parameter the same we declared at the resource // contents file (timedateui.rc). We named the action "tools_insert_timedate". // Here is where we connect it to an actual KDE action. actionCollection()->addAction("tools_insert_timedate", action); action->setShortcut(Qt::CTRL + Qt::Key_D); // As usual, we connect the signal triggered() to a slot here. When the menu // element is clicked, we go to the slot slotInsertTimeDate(). connect(action, SIGNAL(triggered()), this, SLOT(slotInsertTimeDate())); // This is always needed, tell the KDE XML GUI client that we are using // that file for reading actions from. setXMLFile("timedateui.rc"); } // Destructor TimeDatePluginView::~TimeDatePluginView() { } // The slot that will be called when the menu element "Insert Time & Date" is // clicked. void TimeDatePluginView::slotInsertTimeDate() { QString localizedTimeDate = i18nc("This is a localized string for default time & date printing on kate document." "%e means day in XX format." "%m means month in XX format." "%Y means year in XXXX format." "%H means hours in XX format." "%M means minutes in XX format." "Please, if in your language time or date is written in a different order, change it here", "%m-%e-%Y %H:%M"); // We create a KDateTime object with the current time & date. KDateTime dt(QDateTime::currentDateTime()); // We insert the information in the document at the current cursor position // with the default string declared on the header. m_view->document()->insertText(m_view->cursorPosition(), dt.toString(localizedTimeDate)); } // We need to include the moc file since we have declared slots and we are using // the Q_OBJECT macro on the TimeDatePluginView class. #include "timedate.moc" </code> === Building it all, the CMakeLists.txt === Finally, to put everything together you need to build everything, to tell cmake what needs to go where there is the CMakeLists.txt file. For more details on CMake please read [[Development/Tutorials/CMake]] <code bash> find_package(KDE4 REQUIRED) include (KDE4Defaults) include_directories(${KDE4_INCLUDES}) # We are calling our plugin "ktexteditor_timedate", and it contains only # one source file: timedate.cpp. kde4_add_plugin(ktexteditor_timedate timedate.cpp) # We need to link our plugin against kdecore libs, as well as ktexteditor target_link_libraries(ktexteditor_timedate ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS} ktexteditor) # Well, we want to install our plugin on the plugin directory install(TARGETS ktexteditor_timedate DESTINATION ${PLUGIN_INSTALL_DIR}) # We also want to install the resource contents file on the data directory, at # the subdirectory of our plugin name, so it does not mix up with other resource # contents files. install(FILES timedateui.rc DESTINATION ${DATA_INSTALL_DIR}/ktexteditor_timedate) # We want to install the desktop file that describes our plugin too. It will go # on the services directory. install(FILES ktexteditor_timedate.desktop DESTINATION ${SERVICES_INSTALL_DIR}) </code> === The next part === Now you are ready for adding to this plugin a configuration dialog that lets the user customize the way the string is printed out on the screen. [[Development/Tutorials/Kate/KTextEditor_Plugins_Advanced|Take me to the next part of this tutorial !!]]