Difference between revisions of "Building Plugins:MythNotes02"

From MythTV Official Wiki
Jump to: navigation, search
m
(Update for current sources)
 
Line 51: Line 51:
 
unsigned int *g_executed;
 
unsigned int *g_executed;
  
void setupKeys(void)
+
static void setupKeys(void)
 
{
 
{
 
     REG_JUMP("MythNotes", QT_TRANSLATE_NOOP("MythControls",
 
     REG_JUMP("MythNotes", QT_TRANSLATE_NOOP("MythControls",
 
         "Notes taking demonstration plugin"), "", runNotes);
 
         "Notes taking demonstration plugin"), "", runNotes);
 
     REG_KEY("Notes", "EXIT", QT_TRANSLATE_NOOP("MythControls",
 
     REG_KEY("Notes", "EXIT", QT_TRANSLATE_NOOP("MythControls",
    "Exit the Smart Home"), "Q");
+
        "Exit the Smart Home"), "Q");
 
}
 
}
  
Line 62: Line 62:
 
int mythplugin_init(const char *libversion)
 
int mythplugin_init(const char *libversion)
 
{
 
{
VERBOSE(VB_IMPORTANT, LOC + "init");
+
    LOG(VB_GENERAL, LOG_INFO, LOC + "init");
     if (!gContext->TestPopupVersion("mythnotes", libversion,
+
     if (!gCoreContext->TestPluginVersion("mythnotes",  
                                    MYTH_BINARY_VERSION))
+
                                        libversion,
 +
                                        MYTH_BINARY_VERSION))
 
     {
 
     {
         VERBOSE(VB_IMPORTANT,
+
         LOG(VB_GENERAL, LOG_INFO,
 
                 QString("libmythnotes.so/main.o: binary version mismatch"));
 
                 QString("libmythnotes.so/main.o: binary version mismatch"));
 
         return -1;
 
         return -1;
Line 72: Line 73:
  
 
     if (!(g_executed = new unsigned int))
 
     if (!(g_executed = new unsigned int))
    return -1;
+
        return -1;
 
     *g_executed = 0;
 
     *g_executed = 0;
  
Line 103: Line 104:
 
int mythplugin_run(void)
 
int mythplugin_run(void)
 
{
 
{
VERBOSE(VB_IMPORTANT, LOC + "exec");
+
    LOG(VB_GENERAL, LOG_INFO,LOC + "exec");
 
     return RunNotes();
 
     return RunNotes();
 
}
 
}
Line 110: Line 111:
 
int mythplugin_config(void)
 
int mythplugin_config(void)
 
{
 
{
VERBOSE(VB_IMPORTANT, LOC + "config");
+
    LOG(VB_GENERAL, LOG_INFO,LOC + "config");
 
     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
 
     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
 
     NotesUISettings *notes = new NotesUISettings(mainStack, g_executed);
 
     NotesUISettings *notes = new NotesUISettings(mainStack, g_executed);
Line 127: Line 128:
 
void mythplugin_destroy(void)
 
void mythplugin_destroy(void)
 
{
 
{
VERBOSE(VB_IMPORTANT, LOC + "destroy");
+
    LOG(VB_GENERAL, LOG_INFO, LOC + "destroy");
delete g_executed;
+
    delete g_executed;
 
}
 
}
 
</pre>
 
</pre>
Line 171: Line 172:
 
#include <mythuibutton.h>
 
#include <mythuibutton.h>
 
#include <mythdb.h>
 
#include <mythdb.h>
#include <mythverbose.h>
+
 
  
 
class MythUIButton;
 
class MythUIButton;
Line 180: Line 181:
 
class NotesUI : public MythScreenType
 
class NotesUI : public MythScreenType
 
{
 
{
Q_OBJECT
+
  Q_OBJECT
  
 
   public:
 
   public:
NotesUI(MythScreenStack *parentStack, unsigned int *executed,
+
    NotesUI(MythScreenStack *parentStack, unsigned int *executed,
QString name = "MythNotes");
+
            QString name = "MythNotes");
bool Create();
+
    bool Create() override;
bool keyPressEvent(QKeyEvent *event);
+
    bool keyPressEvent(QKeyEvent *event) override;
  
 
   private:
 
   private:
unsigned int *m_executed;
+
    unsigned int *m_executed;
MythUIText *m_title;
+
    MythUIText *m_title;
MythUIText *m_notes;
+
    MythUIText *m_notes;
MythUITextEdit *m_newnote;
+
    MythUITextEdit *m_newnote;
MythUIButton *m_addBtn;
+
    MythUIButton *m_addBtn;
MythUIButton *m_closeBtn;
+
    MythUIButton *m_closeBtn;
  
 
   private slots:
 
   private slots:
void addCallback();
+
    void addCallback();
void closeCallback();
+
    void closeCallback();
 
};
 
};
  
 
class NotesUISettings : public MythScreenType
 
class NotesUISettings : public MythScreenType
 
{
 
{
Q_OBJECT
+
    Q_OBJECT
  
 
   public:
 
   public:
NotesUISettings(MythScreenStack *parentStack, unsigned int *executed);
+
    NotesUISettings(MythScreenStack *parentStack, unsigned int *executed);
bool Create();
+
    bool Create() override;
  
 
   private:
 
   private:
unsigned int *m_executed;
+
    unsigned int *m_executed;
MythUIButton *m_clearBtn;
+
    MythUIButton *m_clearBtn;
 
   private slots:
 
   private slots:
void clearCallback();
+
    void clearCallback();
 
};
 
};
  
Line 236: Line 237:
 
  *
 
  *
 
  */
 
  */
 +
#include <mythuitext.h>
  
 
#include "notesUI.h"
 
#include "notesUI.h"
Line 244: Line 246:
  
 
NotesUI::NotesUI(MythScreenStack *parent, unsigned int *executed, QString name)
 
NotesUI::NotesUI(MythScreenStack *parent, unsigned int *executed, QString name)
: MythScreenType(parent, name), m_title(NULL), m_notes(NULL),
+
        : MythScreenType(parent, name), m_title(NULL), m_notes(NULL),
  m_newnote(NULL), m_addBtn(NULL), m_closeBtn(NULL)
+
        m_newnote(NULL), m_addBtn(NULL), m_closeBtn(NULL)
 
{
 
{
m_executed = executed;
+
    m_executed = executed;
 
}
 
}
  
 
bool NotesUI::Create()
 
bool NotesUI::Create()
 
{
 
{
if (!m_executed) {
+
    if (!m_executed)
VERBOSE(VB_IMPORTANT, LOC + "uninitialized variable m_executed");
+
    {
return false;
+
        LOG(VB_GENERAL, LOG_INFO, LOC + "uninitialized variable m_executed");
}
+
        return false;
 +
    }
  
if (!LoadWindowFromXML("notes-ui.xml", "notesui", this))
+
    if (!LoadWindowFromXML("notes-ui.xml", "notesui", this))
return false;
+
        return false;
  
bool err = false;
+
    bool err = false;
UIUtilE::Assign(this, m_title, "title", &err);
+
    UIUtilE::Assign(this, m_title, "title", &err);
UIUtilE::Assign(this, m_notes, "notes", &err);
+
    UIUtilE::Assign(this, m_notes, "notes", &err);
UIUtilE::Assign(this, m_newnote, "newnote", &err);
+
    UIUtilE::Assign(this, m_newnote, "newnote", &err);
UIUtilE::Assign(this, m_addBtn, "addbtn", &err);
+
    UIUtilE::Assign(this, m_addBtn, "addbtn", &err);
UIUtilE::Assign(this, m_closeBtn, "closebtn", &err);
+
    UIUtilE::Assign(this, m_closeBtn, "closebtn", &err);
if (err)
+
    if (err)
return false;
+
        return false;
  
connect(m_addBtn, SIGNAL(Clicked()), this, SLOT(addCallback()));
+
    connect(m_addBtn, SIGNAL(Clicked()), this, SLOT(addCallback()));
connect(m_closeBtn, SIGNAL(Clicked()), this, SLOT(closeCallback()));
+
    connect(m_closeBtn, SIGNAL(Clicked()), this, SLOT(closeCallback()));
  
*m_executed += 1;
+
    *m_executed += 1;
m_notes->SetText(QString("MythNotes executed: %1").arg(*m_executed));
+
    m_notes->SetText(QString("MythNotes executed: %1").arg(*m_executed));
  
BuildFocusList();
+
    BuildFocusList();
SetFocusWidget(m_newnote);
+
    SetFocusWidget(m_newnote);
  
return true;
+
    return true;
 
}
 
}
  
Line 295: Line 298:
 
         handled = true;
 
         handled = true;
  
         if (action == "ESCAPE") {
+
         if (action == "ESCAPE")  
        closeCallback();
+
        {
         } else {
+
            closeCallback();
 +
         }
 +
        else
 +
        {
 
             handled = false;
 
             handled = false;
 
         }
 
         }
Line 310: Line 316:
 
void NotesUI::addCallback()
 
void NotesUI::addCallback()
 
{
 
{
m_notes->SetText(m_notes->GetText() + "\n\t" + m_newnote->GetText());
+
    m_notes->SetText(m_notes->GetText() + "\n\t" + m_newnote->GetText());
 
}
 
}
  
 
void NotesUI::closeCallback()
 
void NotesUI::closeCallback()
 
{
 
{
Close();
+
    Close();
 
}
 
}
  
Line 321: Line 327:
  
 
NotesUISettings::NotesUISettings(MythScreenStack *parent, unsigned int *executed)
 
NotesUISettings::NotesUISettings(MythScreenStack *parent, unsigned int *executed)
: MythScreenType(parent, "Notes UI Settings"), m_clearBtn(NULL)
+
                : MythScreenType(parent, "Notes UI Settings"), m_clearBtn(NULL)
 
{
 
{
m_executed = executed;
+
    m_executed = executed;
 
}
 
}
  
 
bool NotesUISettings::Create()
 
bool NotesUISettings::Create()
 
{
 
{
if (!m_executed) {
+
    if (!m_executed)  
VERBOSE(VB_IMPORTANT, LOC + "uninitialized variable m_executed");
+
    {
return false;
+
        LOG(VB_GENERAL, LOG_INFO,LOC + "uninitialized variable m_executed");
}
+
        return false;
 +
    }
  
if (!LoadWindowFromXML("notes-ui.xml", "notesuisettings", this))
+
    if (!LoadWindowFromXML("notes-ui.xml", "notesuisettings", this))
return false;
+
        return false;
  
bool err = false;
+
    bool err = false;
UIUtilE::Assign(this, m_clearBtn, "clearbtn", &err);
+
    UIUtilE::Assign(this, m_clearBtn, "clearbtn", &err);
if (err)
+
    if (err)
return false;
+
        return false;
  
connect(m_clearBtn, SIGNAL(Clicked()), this, SLOT(clearCallback()));
+
    connect(m_clearBtn, SIGNAL(Clicked()), this, SLOT(clearCallback()));
  
BuildFocusList();
+
    BuildFocusList();
SetFocusWidget(m_clearBtn);
+
    SetFocusWidget(m_clearBtn);
  
return true;
+
    return true;
 
}
 
}
  
 
void NotesUISettings::clearCallback()
 
void NotesUISettings::clearCallback()
 
{
 
{
*m_executed = 0;
+
    *m_executed = 0;
 
}
 
}
 
</pre>
 
</pre>
Line 380: Line 387:
  
 
         <textedit name="newnote" from="basetextedit">
 
         <textedit name="newnote" from="basetextedit">
             <area>405,80,395,30</area>
+
             <area>405,90,395,50</area>
 
         </textedit>
 
         </textedit>
  
 
         <button name="addbtn" from="basewidebutton">
 
         <button name="addbtn" from="basewidebutton">
             <position>405,130</position>
+
             <position>405,150</position>
 
             <value>Add note</value>
 
             <value>Add note</value>
 
         </button>
 
         </button>
  
 
         <button name="closebtn" from="basewidebutton">
 
         <button name="closebtn" from="basewidebutton">
             <position>405,180</position>
+
             <position>405,200</position>
 
             <value>Close</value>
 
             <value>Close</value>
 
         </button>
 
         </button>

Latest revision as of 17:30, 10 May 2020

Displays how many times was the plug-in executed since mythfrontend start.

  • "Invisible" initialization and clean-up parts
  • Second window for plug-in configuration


Important.png Note: Read the MythNotes introduction Building_Plugins:MythNotes first.

Important.png Note: This tutorial follows-up the Building_Plugins:MythNotes01 tutorial.

C++ code

Script.png /mythnotes/main.cpp

/*
 * Main of MythTV's demonstration plugin MythNotes
 *
 * Copyright (C) 2010 Lukas Doktor <ldoktor@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 */

#include <iostream>
using namespace std;

#include <QApplication>

#include "notesUI.h"

#include <mythversion.h>
#include <mythpluginapi.h>
#include <mythscreentype.h>
#include <mythuihelper.h>
#include <mythmainwindow.h>
#include <mythcontext.h>


#define LOC_ERR QString("MythNotes:MAIN Error: ")
#define LOC_WARN QString("MythNotes:MAIN Warning: ")
#define LOC QString("MythNotes:MAIN: ")

/* Main program run wrappers */
void runNotes(void);
int  RunNotes(void);

unsigned int *g_executed;

static void setupKeys(void)
{
    REG_JUMP("MythNotes", QT_TRANSLATE_NOOP("MythControls",
        "Notes taking demonstration plugin"), "", runNotes);
    REG_KEY("Notes", "EXIT", QT_TRANSLATE_NOOP("MythControls",
        "Exit the Smart Home"), "Q");
}

/* plugin initialization */
int mythplugin_init(const char *libversion)
{
    LOG(VB_GENERAL, LOG_INFO, LOC + "init");
    if (!gCoreContext->TestPluginVersion("mythnotes", 
                                         libversion,
                                         MYTH_BINARY_VERSION))
    {
        LOG(VB_GENERAL, LOG_INFO,
                QString("libmythnotes.so/main.o: binary version mismatch"));
        return -1;
    }

    if (!(g_executed = new unsigned int))
        return -1;
    *g_executed = 0;

    setupKeys();

    return 0;
}

void runNotes(void)
{
    RunNotes();
}

int RunNotes(void)
{
    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    NotesUI *notes = new NotesUI(mainStack, g_executed, "Notes");
    
    if (notes->Create())
    {
        mainStack->AddScreen(notes);
        return 0;
    } else {
        delete notes;
        return -1;
    }
}

/* plugin execution */
int mythplugin_run(void)
{
    LOG(VB_GENERAL, LOG_INFO,LOC + "exec");
    return RunNotes();
}

/* plugin config execution */
int mythplugin_config(void)
{
    LOG(VB_GENERAL, LOG_INFO,LOC + "config");
    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    NotesUISettings *notes = new NotesUISettings(mainStack, g_executed);

    if (notes->Create())
    {
        mainStack->AddScreen(notes);
        return 0;
    } else {
        delete notes;
        return -1;
    }
}

/* plugin clean-up */
void mythplugin_destroy(void)
{
    LOG(VB_GENERAL, LOG_INFO, LOC + "destroy");
    delete g_executed;
}
  • setupKeys()
    • REG_JUMP - Registers the jumps - can maps a function from this plug-in to a key in MythTV configuration
    • REG_KEY - Creates a named key event which can be mapped in MythTV configuration to different key
  • mythplugin_init()
    • Complete initialization
    • First check the libversion
    • Initialize objects/threads/variables
    • Setup additiona keyboards
  • RunNotes(), runNotes(), mythplugin_run()
    • stays the same (notify that mythplugin_run uses RunNotes and REG_JUMP uses runNotes)
  • mythplugin_config()
    • Additional screen. Looks similar with RunNotes only it creates NotesUISettings object instead of NotesUI.
  • mythplugin_destroy()
    • Clean-up


Script.png /mythnotes/notesUI.h

/*
 * Header file for UI
 *
 * Copyright (C) 2010 Lukas Doktor <ldoktor@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 */

#ifndef NOTESUI_H_
#define NOTESUI_H_

#include <QString>
#include <QKeyEvent>

#include <mythscreentype.h>
#include <mythmainwindow.h>
#include <mythdialogbox.h>
#include <mythuibutton.h>
#include <mythdb.h>


class MythUIButton;
class MythUIText;
class MythUITextEdit;
class QKeyEvent;

class NotesUI : public MythScreenType
{
  Q_OBJECT

  public:
    NotesUI(MythScreenStack *parentStack, unsigned int *executed,
            QString name = "MythNotes");
    bool Create() override;
    bool keyPressEvent(QKeyEvent *event) override;

  private:
    unsigned int	*m_executed;
    MythUIText		*m_title;
    MythUIText		*m_notes;
    MythUITextEdit	*m_newnote;
    MythUIButton	*m_addBtn;
    MythUIButton	*m_closeBtn;

  private slots:
    void addCallback();
    void closeCallback();
};

class NotesUISettings : public MythScreenType
{
    Q_OBJECT

  public:
    NotesUISettings(MythScreenStack *parentStack, unsigned int *executed);
    bool Create() override;

  private:
    unsigned int	*m_executed;
    MythUIButton	*m_clearBtn;
  private slots:
    void clearCallback();
};

#endif /* NOTESUI_H_ */
  • class NotesUI
    • (header) is the same as in the previous tutorial
  • class NotesUISettings
    • New window with plug-in setting


Script.png /mythnotes/notesUI.cpp

/*
 * Source file for UIs
 *
 * Copyright (C) 2010 Lukas Doktor <ldoktor@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 */
#include <mythuitext.h>

#include "notesUI.h"

#define LOC_ERR QString("MythNotes:notesUI Error: ")
#define LOC_WARN QString("MythNotes:notesUI Warning: ")
#define LOC QString("MythNotes:notesUI: ")

NotesUI::NotesUI(MythScreenStack *parent, unsigned int *executed, QString name)
        : MythScreenType(parent, name), m_title(NULL), m_notes(NULL),
        m_newnote(NULL), m_addBtn(NULL), m_closeBtn(NULL)
{
    m_executed = executed;
}

bool NotesUI::Create()
{
    if (!m_executed)
    {
        LOG(VB_GENERAL, LOG_INFO, LOC + "uninitialized variable m_executed");
        return false;
    }

    if (!LoadWindowFromXML("notes-ui.xml", "notesui", this))
        return false;

    bool err = false;
    UIUtilE::Assign(this, m_title, "title", &err);
    UIUtilE::Assign(this, m_notes, "notes", &err);
    UIUtilE::Assign(this, m_newnote, "newnote", &err);
    UIUtilE::Assign(this, m_addBtn, "addbtn", &err);
    UIUtilE::Assign(this, m_closeBtn, "closebtn", &err);
    if (err)
        return false;

    connect(m_addBtn, SIGNAL(Clicked()), this, SLOT(addCallback()));
    connect(m_closeBtn, SIGNAL(Clicked()), this, SLOT(closeCallback()));

    *m_executed += 1;
    m_notes->SetText(QString("MythNotes executed: %1").arg(*m_executed));

    BuildFocusList();
    SetFocusWidget(m_newnote);

    return true;
}

bool NotesUI::keyPressEvent(QKeyEvent *event)
{
    if (GetFocusWidget()->keyPressEvent(event))
        return true;

    bool handled = false;
    QStringList actions;
    handled = GetMythMainWindow()->TranslateKeyPress("Notes", event, actions);

    for (int i = 0; i < actions.size() && !handled; i++)
    {
        QString action = actions[i];
        handled = true;

        if (action == "ESCAPE") 
        {
            closeCallback();
        }
        else
        {
            handled = false;
        }
    }

    if (!handled && MythScreenType::keyPressEvent(event))
        handled = true;

    return handled;
}

void NotesUI::addCallback()
{
    m_notes->SetText(m_notes->GetText() + "\n\t" + m_newnote->GetText());
}

void NotesUI::closeCallback()
{
    Close();
}



NotesUISettings::NotesUISettings(MythScreenStack *parent, unsigned int *executed)
                : MythScreenType(parent, "Notes UI Settings"), m_clearBtn(NULL)
{
    m_executed = executed;
}

bool NotesUISettings::Create()
{
    if (!m_executed) 
    {
        LOG(VB_GENERAL, LOG_INFO,LOC + "uninitialized variable m_executed");
        return false;
    }

    if (!LoadWindowFromXML("notes-ui.xml", "notesuisettings", this))
        return false;

    bool err = false;
    UIUtilE::Assign(this, m_clearBtn, "clearbtn", &err);
    if (err)
        return false;

    connect(m_clearBtn, SIGNAL(Clicked()), this, SLOT(clearCallback()));

    BuildFocusList();
    SetFocusWidget(m_clearBtn);

    return true;
}

void NotesUISettings::clearCallback()
{
    *m_executed = 0;
}
  • Defines two window objects which are then used in the "main.cpp"

UI files

Script.png /themes/default/notes-ui.xml

<?xml version="1.0" encoding="utf-8"?>
<mythuitheme>
    <window name="notesui">
        <textarea name="title">
            <area>10,10,780,60</area>
            <font>baselarge</font>
            <align>allcenter</align>
            <multiline>yes</multiline>
            <value>MythNotes</value>
        </textarea>

        <textarea name="notes">
            <area>10,80,395,510</area>
            <font>basemedium</font>
            <align>left,top</align>
            <multiline>yes</multiline>
        </textarea>

        <textedit name="newnote" from="basetextedit">
            <area>405,90,395,50</area>
        </textedit>

        <button name="addbtn" from="basewidebutton">
            <position>405,150</position>
            <value>Add note</value>
        </button>

        <button name="closebtn" from="basewidebutton">
            <position>405,200</position>
            <value>Close</value>
        </button>
    </window>
    
    <window name="notesuisettings">
    	<textarea name="title">
            <area>10,10,780,60</area>
            <font>baselarge</font>
            <align>allcenter</align>
            <multiline>yes</multiline>
            <value>Notes Settings</value>
        </textarea>
        
        <button name="clearbtn" from="basewidebutton">
            <position>30,80</position>
            <value>Clear No. Executions</value>
        </button>
    </window>
</mythuitheme>
  • In XML file we need to define two windows. Based on the "name" they are than loaded from C++ file and the UI widgets are assigned and used in the code.


Remaining files

No changes here

Compile & Run

See the first part Building_Plugins:MythNotes00.

Recapitulation

  • copy the plug-in from the first part (Building_Plugins:MythNotes01)
  • Modify the C++ code (Complete initialization, add new window and define clean-up)
  • Modify the XML UI layout (Add second screen)

Next tutorial

Important.png Note: You have successfully finished the Complete plug-in tutorial. Let's move on to the next level - "Storing the information" (Building_Plugins:MythNotes03)