Another Plasmoid Guide: Configuration, Events, and Notifications

    Dr.Konqi, we are friends with him, I often see him%)

    Instead of the foreword

    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



    class QGraphicsLinearLayout;
    class oblikuestrategies : public Plasma::Applet
      oblikuestrategies(QObject *parent, const QVariantList &args);
      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();
      void createConfigurationInterface(KConfigDialog *parent);
      // 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"
    oblikuestrategies::oblikuestrategies(QObject *parent, const QVariantList &args) :
      Plasma::Applet(parent, args)
      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)
      // generate ui
      // layout
      QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
      // label
      main_label = new Plasma::Label(this);
      main_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      main_label->setToolTip(qApp->translate("tooltip", "Click here to update message"));
      // copyright label
      info_label = new Plasma::Label(this);

    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.

    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;
      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)

    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);

    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()));
    // считывание переменных
      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.

    First, create a plasma_applet_oblikue-strategies.notifyrc file
    Name=Oblikue Strategies
    Comment=Oblikue Strategies
    Name=New message
    Comment=There is auto updated message in widget

    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->setTitle(QString(i18n("Oblikue Strategies")));
      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.

    ls -1 sources

    project (plasma_applet_oblikue-strategies)
    find_package (KDE4 REQUIRED)
    include (KDE4Defaults)
    add_definitions (${QT_DEFINITIONS} 
    include_directories (${CMAKE_SOURCE_DIR} 
    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

    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.


    Sources of this disgrace.
    What happened:

    Based on materials

    Thank you for your attention!

    Also popular now: