Neverendingo (Talk | contribs) m (Text replace - "<code cppqt>" to "<syntaxhighlight lang="cpp-qt">") |
|||
Line 73: | Line 73: | ||
=== The header file === | === The header file === | ||
'''timedate.h''' | '''timedate.h''' | ||
− | < | + | <syntaxhighlight lang="cpp-qt"> |
// Avoid multiple header inclusion | // Avoid multiple header inclusion | ||
#ifndef TIMEDATE_H | #ifndef TIMEDATE_H | ||
Line 168: | Line 168: | ||
=== The source file === | === The source file === | ||
'''timedate.cpp''' | '''timedate.cpp''' | ||
− | < | + | <syntaxhighlight lang="cpp-qt"> |
// Own includes | // Own includes | ||
#include "timedate.h" | #include "timedate.h" |
Tutorial Series | Kate Plugin Tutorial |
Previous | C++, Qt, KDE4 development environment |
What's Next | Add a configuration dialog for it (Work in progress) |
Further Reading | CMake, The actual plugin code |
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
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>
timedate.h
// 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 default string that will be printed out. As not everybody prints
// it by default as: MM-DD-YYYY HH:MM, but for example, on other cultures we can
// find DD-MM-YYYY HH:MM, we mark this default string for translators to translate
// it. With this macro I18N_NOOP2 we are able to add comments for making the translation
// easier and in context. If a translator sees "%m-%e-%Y %H:%M" can think: "what is this
// guy talking about?". So we add the explanation on the first parameter.
// Anyway, this is not important, do not get stucked here. If you do not understand
// this declaration, think of it as:
//
// static QString localizedTimeDate = "%m-%e-%Y %H:%M";
static QString localizedTimeDate =
I18N_NOOP2("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");
/**
* 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 = 0,
const QStringList &args = QStringList());
// 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();
virtual void readConfig (KConfig *) {}
virtual void writeConfig (KConfig *) {}
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'''
<syntaxhighlight lang="cpp-qt">
// Own includes
#include "timedate.h"
// Include the basics
#include <ktexteditor/document.h>
#include <kgenericfactory.h>
#include <klocale.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kdatetime.h>
// Without this macro call, the library loader won't find our plugin when trying
// to load it. This macro adds code automagically that will let our plugin
// be loaded on runtime.
// The first parameter is the X-KDE-FactoryName on the .desktop file.
// As we haven't provided such parameter, in this case (because our library is only
// exporting one symbol, this plugin), we put here the X-KDE-LibraryName.
// The second parameter will determine which type is our class, in this case it is
// a TimeDatePlugin and the name of the X-KDE-FactoryName again. Same as before,
// as we do not have X-KDE-FactoryName, we put there the X-KDE-LibraryName.
// Is important to provide as last parameter "ktexteditor_plugins".
K_EXPORT_COMPONENT_FACTORY(ktexteditor_timedate, KGenericFactory<TimeDatePlugin>("ktexteditor_timedate", "ktexteditor_plugins"))
// Constructor
TimeDatePlugin::TimeDatePlugin(QObject *parent, const QStringList &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)
{
// Insert the plugin
view->insertChildClient(this);
setComponentData(KGenericFactory<TimeDatePlugin>::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()
{
// 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>
# 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} 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.