Building Plugins:MythNotes03

From MythTV Official Wiki
Revision as of 11:38, 11 February 2011 by Ldoktor (talk | contribs) (0.24 update)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Stores full-text notes in one big textarea.

  • Internal storage gContext
  • Basic SQL storage


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

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

C++ code

In this example are displayed two kinds of storing informations commonly used in MythTV.

  • mythcontext - QString storage with QString key. Allows per frontend or general storage.
  • mythdb - MySQL driver.


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

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)
{
	VERBOSE(VB_IMPORTANT, LOC + "init");
    if (!gContext->TestPopupVersion("mythnotes", libversion,
                                    MYTH_BINARY_VERSION))
    {
        VERBOSE(VB_IMPORTANT,
                QString("libmythnotes.so/main.o: binary version mismatch"));
        return -1;
    }

    gCoreContext->ActivateSettingsCache(false);
    QString hostname = gCoreContext->GetHostName();
    if (gCoreContext->GetSettingOnHost("NotesExecuted", hostname).isEmpty()) {
    	gCoreContext->SaveSettingOnHost("NotesExecuted", "False", hostname);
    }
    if (gCoreContext->GetSetting("NotesExecutedCount").isEmpty()) {
    	gCoreContext->SaveSetting("NotesExecutedCount", "0");
    }
    gCoreContext->ActivateSettingsCache(true);

    setupKeys();

    return 0;
}

void runNotes(void)
{
    RunNotes();
}

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

/* plugin execution */
int mythplugin_run(void)
{
	VERBOSE(VB_IMPORTANT, LOC + "exec");
    return RunNotes();
}

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

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

/* plugin clean-up */
void mythplugin_destroy(void)
{
	VERBOSE(VB_IMPORTANT, LOC + "destroy");
}
  • include gContext and SQL
  • mythplugin_init()
    • Check default gContext setting (per host and general)


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>
#include <mythverbose.h>
#include <mythcontext.h>


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

class NotesUI : public MythScreenType
{
	Q_OBJECT

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

  private:
	MythUIText		*m_title;
	MythUIText		*m_notes;
	MythUITextEdit	*m_table;
	MythUIButton	*m_selectBtn;
	MythUIButton	*m_closeBtn;

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

class NotesUISettings : public MythScreenType
{
	Q_OBJECT

  public:
	NotesUISettings(MythScreenStack *parentStack);
	bool Create();

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

#endif /* NOTESUI_H_ */
  • minor changes in includes, variables and private slots


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 "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, QString name)
		: MythScreenType(parent, name), m_title(NULL), m_notes(NULL),
		  m_table(NULL), m_selectBtn(NULL), m_closeBtn(NULL)
{
}

bool NotesUI::Create()
{
	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_table, "table", &err);
	UIUtilE::Assign(this, m_selectBtn, "selectbtn", &err);
	UIUtilE::Assign(this, m_closeBtn, "closebtn", &err);
	if (err)
		return false;

	connect(m_selectBtn, SIGNAL(Clicked()), this, SLOT(selectCallback()));
	connect(m_closeBtn, SIGNAL(Clicked()), this, SLOT(closeCallback()));

	/* NOT LOCKED, DEMONSTRATION ONLY */
	gCoreContext->ActivateSettingsCache(false);
    QString hostname = gCoreContext->GetHostName();
    if (gCoreContext->GetSettingOnHost("NotesExecuted", hostname) != "True") {
    	gCoreContext->SaveSettingOnHost("NotesExecuted", "True", hostname);
        m_title->SetText("MythNotes HOST ");
    } else {
    	m_title->SetText("MythNotes ");
    }
    int executed = (gCoreContext->GetSetting("NotesExecutedCount")).toInt() + 1;
    gCoreContext->SaveSetting("NotesExecutedCount", executed);
    gCoreContext->ActivateSettingsCache(true);
	m_title->SetText(m_title->GetText() + QString(" %1").arg(executed));

	BuildFocusList();
	SetFocusWidget(m_table);

	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::selectCallback()
{
	MSqlQuery db(MSqlQuery::InitCon());
	QString query = QString("SELECT * "
							"FROM %1").arg(m_table->GetText());
	if (!db.exec(query)) {
		MythDB::DBError("Notes select tables", db);
		m_notes->SetText("Error occured");
		return;
	}
	m_notes->SetText("");
	while (db.next()) {
		m_notes->SetText(m_notes->GetText() + "\n" + db.value(0).toString());
	}
}

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



NotesUISettings::NotesUISettings(MythScreenStack *parent)
				: MythScreenType(parent, "Notes UI Settings"), m_clearBtn(NULL)
{
}

bool NotesUISettings::Create()
{
	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()
{
    gCoreContext->ActivateSettingsCache(false);
    gCoreContext->SaveSetting("NotesExecutedCount", "0");
    gCoreContext->ActivateSettingsCache(true);
}
  • NotesUI::Create()
    • Assigns UIs
    • connects signals->slots
    • modifies UI texts accordingly to setting
    • builds focus'
  • NotesUI::selectCallback()
    • creates DB connection
    • executes the querry (SQL syntax)
    • while (db.next()) - goes through results; stores the current line in db.value()

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="table" from="basetextedit">
            <area>405,80,395,30</area>
        </textedit>

        <button name="selectbtn" from="basewidebutton">
            <position>405,130</position>
            <value>Display table</value>
        </button>

        <button name="closebtn" from="basewidebutton">
            <position>405,180</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 Global No. Executions</value>
        </button>
    </window>
</mythuitheme>
  • Only minor changes you already know

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:MythNotes02)
  • Modify the C++ code (includes, init, gContext, SQL, ...)
  • Modify the XML UI layout (minor changes)

Next tutorial

Important.png Note: You have successfully finished the Storing the information tutorial. Let's move on to the next level - "Advanced UI" (Building_Plugins:MythNotes04)