Abstract

note: this project has bitrot and does not build!

The plugin that we developed on the previous part of this tutorial was nice, but probably not enough. We also need it to be configurable, because the user might want to only add to his/her document the date or the time, not both. We are going to create a configuration dialog for the plugin, and make the output form of our time & date configurable by the user.

The Code

The .desktop files

Every plugin needs a .desktop file that describes it. Same for each configuration page/widget. As we only need a page/widget for this plugin, we will only have two desktop files: one for the plugin itself, and another one for configuration the page/widget.

ktexteditor_timedate.desktop

[Desktop Entry]Encoding=UTF-8X-KDE-Library=ktexteditor_timedateX-KDE-PluginKeyword=ktexteditor_timedateX-KDE-PluginInfo-Author=Konqui the DragonX-KDE-PluginInfo-Email=konqui@kde.orgX-KDE-PluginInfo-Name=ktexteditortimedateX-KDE-PluginInfo-Version=0.1X-KDE-PluginInfo-Website=http://kate.kde.orgX-KDE-PluginInfo-Category=EditorX-KDE-PluginInfo-Depends=X-KDE-PluginInfo-License=GPLX-KDE-PluginInfo-EnabledByDefault=falseX-KDE-ParentApp=kateX-KDE-Version=4.0ServiceTypes=KTextEditor/PluginType=ServiceIcon=korganizerName=Time & DateComment=Insert current Time & Date

X-KDE-Library: you need to specify which library provides this configuration dialog. In this case we are shipping on the same library "ktexteditor_timedate.so" both the plugin itself and its configuration dialog.

X-KDE-PluginKeyword: since we have two entry points on the library at this time: one for the plugin and another one for the configuration dialog we need to specify which keyword has each one. As you can see I also added this entry to the ktexteditor_timedate.desktop file. Of course they have to be different if we want to see it working.

The resource contents 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.

The header file of the plugin

timedate.h

#ifndef TIMEDATE_H#define TIMEDATE_H#include<ktexteditor/plugin.h>#include<ktexteditor/view.h>#include<kxmlguiclient.h>#include<klocalizedstring.h>#include<kpluginfactory.h>#include<QtCore/QEvent>#include<QtCore/QObject>#include<QtCore/QList>#include<QtCore/QVariantList>/** * Variable that will contain the localized time & date format * at the beginning. */staticQStringlocalizedTimeDate=QString();classTimeDatePlugin:publicKTextEditor::Plugin{public:explicitTimeDatePlugin(QObject*parent=0,constQVariantList&args=QVariantList());virtual~TimeDatePlugin();/** * Since the plugin has a singleton structure, it will be created * only once, we return the instance of the plugin. * * It may return 0 if no plugin instance has been created. This has * to be taken in count specially when designing the configuration * dialog. */staticTimeDatePlugin*self(){returnplugin;}/** * Method for merging with the KTextEditor view. */voidaddView(KTextEditor::View*view);/** * Method for removing from the KTextEditor view. */voidremoveView(KTextEditor::View*view);/** * Methods for reading and writing the configuration * preferences. */voidreadConfig();voidwriteConfig();virtualvoidreadConfig(KConfig*){}virtualvoidwriteConfig(KConfig*){}/** * Set the format that will be used to print the * date and time string. */voidsetFormat(constQString&format);/** * Returns the current format that will be used to * print the date and time string. */QStringformat()const;private:staticTimeDatePlugin*plugin;QList<classTimeDatePluginView*>m_views;QStringm_string;};classTimeDatePluginView:publicQObject,publicKXMLGUIClient{Q_OBJECTpublic:explicitTimeDatePluginView(constQString&string,KTextEditor::View*view=0);~TimeDatePluginView();/** * Set the format for this view. */voidsetFormat(constQString&format);QStringformat()const;privateQ_SLOTS:/** * This slot is called when the user wants to insert the * time & date onto the document. */voidslotInsertTimeDate();private:KTextEditor::View*m_view;QStringm_string;};K_PLUGIN_FACTORY_DECLARATION(TimeDatePluginFactory)#endif // TIMEDATE_H

The source file of the plugin

timedate.cpp

#include"timedate.h"#include"timedate_config.h"#include<ktexteditor/document.h>#include<kpluginfactory.h>#include<kpluginloader.h>#include<klocale.h>#include<kaction.h>#include<kactioncollection.h>#include<kdatetime.h>#include<kconfiggroup.h>TimeDatePlugin*TimeDatePlugin::plugin=0;K_PLUGIN_FACTORY_DEFINITION(TimeDatePluginFactory,registerPlugin<TimeDatePlugin>("ktexteditor_timedate");registerPlugin<TimeDateConfig>("ktexteditor_timedate_config");)K_EXPORT_PLUGIN(TimeDatePluginFactory("ktexteditor_timedate","ktexteditor_plugins"))TimeDatePlugin::TimeDatePlugin(QObject*parent,constQVariantList&args):KTextEditor::Plugin(parent){Q_UNUSED(args);if(localizedTimeDate.isNull()){localizedTimeDate=i18nc("This is a localized string for default time & date printing on kate document.""%d 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","%d-%m-%Y %H:%M");}plugin=this;readConfig();}TimeDatePlugin::~TimeDatePlugin(){plugin=0;}voidTimeDatePlugin::addView(KTextEditor::View*view){TimeDatePluginView*nview=newTimeDatePluginView(m_string,view);m_views.append(nview);}voidTimeDatePlugin::removeView(KTextEditor::View*view){for(intz=0;z<m_views.size();z++){if(m_views.at(z)->parentClient()==view){TimeDatePluginView*nview=m_views.at(z);m_views.removeAll(nview);deletenview;}}}voidTimeDatePlugin::readConfig(){KConfigGroupcg(KGlobal::config(),"TimeDate Plugin");m_string=cg.readEntry("string",localizedTimeDate);}voidTimeDatePlugin::writeConfig(){KConfigGroupcg(KGlobal::config(),"TimeDate Plugin");cg.writeEntry("string",m_string);}voidTimeDatePlugin::setFormat(constQString&format){m_string=format;// If the property has been set for the plugin in general, let's set that// property to that value on all views where the plugin has been loaded.foreach(TimeDatePluginView*pluginView,m_views){pluginView->setFormat(format);}}QStringTimeDatePlugin::format()const{returnm_string;}TimeDatePluginView::TimeDatePluginView(constQString&string,KTextEditor::View*view):QObject(view),KXMLGUIClient(view),m_view(view),m_string(string){setComponentData(TimeDatePluginFactory::componentData());KAction*action=newKAction(i18n("Insert Time && Date"),this);actionCollection()->addAction("tools_insert_timedate",action);action->setShortcut(Qt::CTRL+Qt::Key_D);connect(action,SIGNAL(triggered()),this,SLOT(slotInsertTimeDate()));setXMLFile("timedateui.rc");}TimeDatePluginView::~TimeDatePluginView(){}voidTimeDatePluginView::setFormat(constQString&format){m_string=format;}QStringTimeDatePluginView::format()const{returnm_string;}voidTimeDatePluginView::slotInsertTimeDate(){KDateTimedt(QDateTime::currentDateTime());m_view->document()->insertText(m_view->cursorPosition(),dt.toString(m_string));}#include"timedate.moc"

The source file of the configuration dialog

timedate_config.cpp

#include"timedate_config.h"#include"timedate.h"#include<QtGui/QLabel>#include<QtGui/QBoxLayout>#include<klocale.h>#include<kpluginfactory.h>#include<kpluginloader.h>#include<klineedit.h>#include<kconfiggroup.h>TimeDateConfig::TimeDateConfig(QWidget*parent,constQVariantList&args):KCModule(TimeDatePluginFactory::componentData(),parent,args){QVBoxLayout*layout=newQVBoxLayout(this);QLabel*info=newQLabel(i18n("%y\t2-digit year excluding century (00 - 99)\n""%Y\tfull year number\n""%:m\tmonth number, without leading zero (1 - 12)\n""%m\tmonth number, 2 digits (01 - 12)\n""%b\tabbreviated month name\n""%B\tfull month name\n""%e\tday of the month (1 - 31)\n""%d\tday of the month, 2 digits (01 - 31)\n""%a\tabbreviated weekday name\n""%A\tfull weekday name\n""\n""%H\thour in the 24 hour clock, 2 digits (00 - 23)\n""%k\thour in the 24 hour clock, without leading zero (0 - 23)\n""%I\thour in the 12 hour clock, 2 digits (01 - 12)\n""%l\thour in the 12 hour clock, without leading zero (1 - 12)\n""%M\tminute, 2 digits (00 - 59)\n""%S\tseconds (00 - 59)\n""%P\t\"am\" or \"pm\"\n""%p\t\"AM\" or \"PM\"\n"));// It is possible that the plugin has not been loaded yet, and the// configuration dialog has been asked to be shown. In that case, it is our// turn to set the static string to the correct value.if(localizedTimeDate.isNull()){localizedTimeDate=i18nc("This is a localized string for default time & date printing on kate document.""%d 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","%d-%m-%Y %H:%M");}QHBoxLayout*hlayout=newQHBoxLayout(this);QLabel*lformat=newQLabel(i18n("Format"));format=newKLineEdit(this);hlayout->addWidget(lformat);hlayout->addWidget(format);layout->addWidget(info);layout->addLayout(hlayout);setLayout(layout);load();QObject::connect(format,SIGNAL(textChanged(QString)),this,SLOT(slotChanged()));}TimeDateConfig::~TimeDateConfig(){}voidTimeDateConfig::save(){if(TimeDatePlugin::self()){TimeDatePlugin::self()->setFormat(format->text());TimeDatePlugin::self()->writeConfig();}else{KConfigGroupcg(KGlobal::config(),"TimeDate Plugin");cg.writeEntry("string",format->text());}emitchanged(false);}voidTimeDateConfig::load(){if(TimeDatePlugin::self()){TimeDatePlugin::self()->readConfig();format->setText(TimeDatePlugin::self()->format());}else{KConfigGroupcg(KGlobal::config(),"TimeDate Plugin");format->setText(cg.readEntry("string",localizedTimeDate));}emitchanged(false);}voidTimeDateConfig::defaults(){format->setText(localizedTimeDate);emitchanged(true);}voidTimeDateConfig::slotChanged(){emitchanged(true);}#include"timedate_config.moc"

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.