Another Plasmoid Guide: Configuration, Events, and Notifications
Dr.Konqi, we are friends with him, I often see him%)
Instead of the foreword
Hello!
On a habr already wrote that all plasmoids need to be ported to QML / JS, but all the same I continue to mock at the CPP corpse and write widgets for plasma on pluses. But maybe not everything is so bad,% username%?
For a simpler example of writing a plasmoid in C ++, you can refer to this article. In this article, we will try to add a few features to the naked widget (in ascending order) - the configuration interface, processing of some events and notifications.
If anyone is interested - continued below.
Widget idea
Since the task for me was exclusively educational and self-educational, the idea of the widget is simple: take and fork the Oblique Strategies widget for GNOME. Thus, in our widget there will be:
- Label with text from cards.
- Label with copyright (primarily used to indicate the current edition)
- Configuration interface, including text settings and editor selection
- Click-to-text update
- Optional auto-update feature
- Optional function to display the current message when automatically changing to standard notifications
Components
Widget
Leader
#ifndef OBLIKUESTRATEGIES_H
#define OBLIKUESTRATEGIES_H
#include
#include
#include
class QGraphicsLinearLayout;
class oblikuestrategies : public Plasma::Applet
{
Q_OBJECT
public:
oblikuestrategies(QObject *parent, const QVariantList &args);
~oblikuestrategies();
int setMessagesText();
void init();
public slots:
int autoUpdateEvent();
int sendNotification(QString eventId, int num);
int updateEvent();
void mousePressEvent(QGraphicsSceneMouseEvent *event);
// for configuration interface
int setAutoUpdate();
void configAccepted();
void configChanged();
protected:
void createConfigurationInterface(KConfigDialog *parent);
private:
// ui
Plasma::Label *main_label;
Plasma::Label *info_label;
QTimer *timer;
// variables
bool autoUpdate_bool, notify_bool;
int autoUpdate_int, edition, fontSize, fontWeight;
QString fontFamily, fontColor, fontStyle;
QStringList formatLine, copyright;
QList mess;
// configuration interface
Ui::ConfigWindow uiConfig;
};
K_EXPORT_PLASMA_APPLET(oblikue-strategies, oblikuestrategies)
#endif /* OBLIKUESTRATEGIES_H */
It will be a kind of "map". The essence of K_EXPORT_PLASMA_APPLET is described in the above article (this is the only fundamentally important thing in the header). Connect the original libraries, declare the class and destructor
#include "oblikue-strategies.h"
#include
#include
oblikuestrategies::oblikuestrategies(QObject *parent, const QVariantList &args) :
Plasma::Applet(parent, args)
{
setBackgroundHints(DefaultBackground);
setHasConfigurationInterface(true);
}
oblikuestrategies::~oblikuestrategies()
{
delete info_label;
delete main_label;
delete timer;
}
nothing really interesting. I only note that we have established here that the applet has a configuration interface. The essence of the variables will be clear below. Next, we assemble the initialization function:
void oblikuestrategies::init()
{
if (setMessagesText() != 0)
return;
// generate ui
// layout
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
layout->setOrientation(Qt::Vertical);
// label
layout->addStretch(1);
main_label = new Plasma::Label(this);
main_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
main_label->setToolTip(qApp->translate("tooltip", "Click here to update message"));
layout->addItem(main_label);
layout->addStretch(1);
// copyright label
info_label = new Plasma::Label(this);
layout->addItem(info_label);
}
The int setMessagesText () function clogs the copyright variables and the actual text of the cards ( mess ), simultaneously creates a list of two formatLine elements . Then we create a Layout, on it two labels - one for the text, the other for copyright - and we will throw stretch for a beautiful look. Next, let's move on to the configuration interface.
Configuration
Let's draw a cookie. Let it be like this:
Now we fasten the functions. Config reading:
void oblikuestrategies::configChanged()
{
KConfigGroup cg = config();
edition = cg.readEntry("edition", 1);
fontFamily = cg.readEntry("font_family", "Terminus");
...
}
I’ll draw your attention to how variables are read. The readEntry method has two arguments - the first variable name in the configuration file (in the back of the hamster plasma-desktop-appletrc ), the second is the default value. Settings recorded using KConfigGroup will be saved in the above file. I will add that this function is automatically called if the widget settings have been changed.
Do not forget about the config entry:
void oblikuestrategies::configAccepted()
{
KConfigGroup cg = config();
cg.writeEntry("edition", uiConfig.comboBox_edition->currentIndex()+1);
cg.writeEntry("font_family", uiConfig.fontComboBox_font->currentFont().family());
...
}
Similar to reading. The writeEntry method also has 2 arguments - the name and where to get the values from. Now screw the interface itself:
void oblikuestrategies::createConfigurationInterface(KConfigDialog *parent)
{
QWidget *configwin = new QWidget;
uiConfig.setupUi(configwin);
uiConfig.comboBox_edition->setCurrentIndex(edition-1);
...
parent->addPage(configwin, i18n("Oblikue Strategies"), Applet::icon());
connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
}
They declared the interface, set the values (the variables have already been read in init () by calling the configChanged () method ). Then we added an interface to the window (the addPage method is the first argument that, the second as the name and the third icon). And they connected the button with saving the settings. Next we fasten the events.
Event handling
Suppose we have some method that is responsible for updating the text. Call it int updateEvent () (returns the number of the called message). Screw the mouse click processing:
void oblikuestrategies::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
// mouse click event
if (event->buttons() == Qt::LeftButton)
updateEvent();
}
If double-clicking, then you need to inherit from mouseDoubleClickEvent and, obviously, checking for the button is not needed. Now add auto-update. First, add a timer declaration to the init () method :
...
// timer
timer = new QTimer(this);
timer->setSingleShot(false);
...
Set it to "reusable" use ( setSingleShot (false) ). Next, turn off and on the timer in the configChanged () method :
if (autoUpdate_bool == true)
{
disconnect(timer, SIGNAL(timeout()), this, SLOT(autoUpdateEvent()));
timer->stop();
}
// считывание переменных
...
if (autoUpdate_bool == true)
{
connect(timer, SIGNAL(timeout()), this, SLOT(autoUpdateEvent()));
timer->start(autoUpdate_int * MSEC_IN_MIN);
}
Just in case: the start () method has an argument of period in ms. Add auto-update function:
int oblikuestrategies::autoUpdateEvent()
{
// auto update text
int num = updateEvent();
if (notify_bool == true)
if (sendNotification(QString("newMessage"), num) != 0)
return 1;
return 0;
}
Here we needed the value returned by the updateEvent () method . This method causes the text to be updated, then if notify_bool == true is set, it calls the method that sends notifications to KDE.
Notifications
First, create a plasma_applet_oblikue-strategies.notifyrc file
[Global]
IconName=oblikue-strategies
Name=Oblikue Strategies
Comment=Oblikue Strategies
[Event/newMessage]
Name=New message
Comment=There is auto updated message in widget
Action=Popup
The first is the general settings, they can be left without comments. Next is a listing of events and what they are. Now back to the source. One single method:
int oblikuestrategies::sendNotification(QString eventId, int num)
{
// send notification
KNotification *notification = new KNotification(eventId);
notification->setComponentData(KComponentData("plasma_applet_oblikue-strategies"));
notification->setTitle(QString(i18n("Oblikue Strategies")));
notification->setText(mess[edition-1][num]);
notification->sendEvent();
delete notification;
return 0;
}
eventId - actually our event. In the setComponentData method , specify the name of the applet (so as not to get confused and for simplicity). We put a signature, text and send a message to the system.
Assembly
ls -1 sources
CMakeLists.txt
configwindow.ui
oblikue-strategies.cpp
oblikue-strategies.h
oblikue-strategies.png
plasma-applet-oblikue-strategies.desktop
plasma_applet_oblikue-strategies.notifyrc
CMakeLists.txt
project (plasma_applet_oblikue-strategies)
find_package (KDE4 REQUIRED)
include (KDE4Defaults)
add_definitions (${QT_DEFINITIONS}
${KDE4_DEFINITIONS})
include_directories (${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
${KDE4_INCLUDES})
set (PLUGIN_NAME ${PROJECT_NAME})
file (GLOB PROJECT_DESKTOP *.desktop)
file (GLOB PROJECT_ICON *.png)
file (GLOB PROJECT_NOTIFY *.notifyrc)
file (GLOB PROJECT_SOURCE *.cpp)
file (GLOB PROJECT_UI *.ui)
kde4_add_ui_files (PROJECT_SOURCE ${PROJECT_UI})
kde4_add_plugin (${PLUGIN_NAME} ${PROJECT_SOURCE})
target_link_libraries (${PLUGIN_NAME} ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS})
# install
install (TARGETS ${PLUGIN_NAME} DESTINATION ${PLUGIN_INSTALL_DIR})
install (FILES ${PROJECT_DESKTOP} DESTINATION ${SERVICES_INSTALL_DIR})
install (FILES ${PROJECT_ICON} DESTINATION ${ICON_INSTALL_DIR})
install (FILES ${PROJECT_NOTIFY} DESTINATION ${DATA_INSTALL_DIR}/${PLUGIN_NAME})
The file is not entirely correct (from the point of view of the human factor, for example), but universal (change only the project name to the desired one). Of the differences from regular assembly files, calling kde4_add_ui_files to create a configuration interface. And installation of the file with notifications.
P.S
Sources of this disgrace.
What happened:
Based on materials
Thank you for your attention!