From b5624f2a89c67abdce94d746ed73c9b097fadfb4 Mon Sep 17 00:00:00 2001 From: Jim Stichnoth Date: Wed, 15 May 2013 16:34:47 -0700 Subject: [PATCH] Themed menus: clean up the classes/interface. This prepares for converting more TV Playback menus into equivalent themed menus. Refs #11533 --- mythtv/libs/libmythtv/tv_play.cpp | 170 +++++++++++++++++------------- mythtv/libs/libmythtv/tv_play.h | 91 +++++++++------- 2 files changed, 151 insertions(+), 110 deletions(-) diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp index 40dac3407ae..8be43dc54f4 100644 --- a/mythtv/libs/libmythtv/tv_play.cpp +++ b/mythtv/libs/libmythtv/tv_play.cpp @@ -20,8 +20,6 @@ using namespace std; #include #include -Q_DECLARE_METATYPE(QDomNode) - #include "signalhandling.h" #include "mythdb.h" #include "tv_play.h" @@ -196,6 +194,18 @@ class DDLoader : public QRunnable QWaitCondition m_wait; }; +class MenuNodeTuple +{ +public: + MenuNodeTuple(const MenuBase &menu, const QDomNode &node) : + m_menu(menu), m_node(node) {} + MenuNodeTuple(void) : m_menu(MenuBase()) {} + const MenuBase &m_menu; + const QDomNode m_node; +}; + +Q_DECLARE_METATYPE(MenuNodeTuple) + /** * \brief If any cards are configured, return the number. */ @@ -9186,13 +9196,14 @@ void TV::customEvent(QEvent *e) { DialogCompletionEvent *dce = reinterpret_cast(e); - if (dce->GetData().userType() == qMetaTypeId()) + if (dce->GetData().userType() == qMetaTypeId()) { - QDomNode data = qVariantValue(dce->GetData()); + MenuNodeTuple data = qVariantValue(dce->GetData()); if (dce->GetResult() == -1) // menu exit/back - MenuShow(data.parentNode(), data); + PlaybackMenuShow(data.m_menu, data.m_node.parentNode(), + data.m_node); else - MenuShow(data, QDomNode()); + PlaybackMenuShow(data.m_menu, data.m_node, QDomNode()); } else OSDDialogEvent(dce->GetResult(), dce->GetResultText(), @@ -10972,10 +10983,10 @@ void TV::HandleOSDInfo(PlayerContext *ctx, QString action) } } -bool MenuBase::MenuLoadFromFile(const QString &filename, - const QString &menuname, - const char *translationContext, - const QString &keyBindingContext) +bool MenuBase::Load(const QString &filename, + const QString &menuname, + const char *translationContext, + const QString &keyBindingContext) { bool result = false; @@ -10992,19 +11003,18 @@ bool MenuBase::MenuLoadFromFile(const QString &filename, QFile file(themefile); if (file.open(QIODevice::ReadOnly)) { - m_menuDocument = new QDomDocument(); - if (m_menuDocument->setContent(&file)) + m_document = new QDomDocument(); + if (m_document->setContent(&file)) { result = true; - m_menuName = - MenuTranslate(MenuGetRoot().attribute("text", menuname)); - QDomElement root = MenuGetRoot(); - MenuProcessIncludes(root); + QDomElement root = GetRoot(); + m_menuName = Translate(root.attribute("text", menuname)); + ProcessIncludes(root); } else { - delete m_menuDocument; - m_menuDocument = NULL; + delete m_document; + m_document = NULL; } file.close(); } @@ -11017,7 +11027,7 @@ bool MenuBase::MenuLoadFromFile(const QString &filename, return result; } -void MenuBase::MenuProcessIncludes(QDomElement &root) +void MenuBase::ProcessIncludes(QDomElement &root) { const int maxRecursion = 10; for (QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling()) @@ -11028,6 +11038,8 @@ void MenuBase::MenuProcessIncludes(QDomElement &root) if (e.tagName() == "include") { QString include = e.attribute("file", ""); + if (include.isEmpty()) + continue; int level = m_recursionLevel + 1; if (level > maxRecursion) { @@ -11039,19 +11051,20 @@ void MenuBase::MenuProcessIncludes(QDomElement &root) } MenuBase menu; menu.m_recursionLevel = level; - if (menu.MenuLoadFromFile(include, include, - m_translationContext, - m_keyBindingContext)) + if (menu.Load(include, + include, // fallback menu name is filename + m_translationContext, + m_keyBindingContext)) { - QDomNode newChild = menu.MenuGetRoot(); - newChild = m_menuDocument->importNode(newChild, true); + QDomNode newChild = menu.GetRoot(); + newChild = m_document->importNode(newChild, true); root.replaceChild(newChild, n); n = newChild; } } else if (e.tagName() == "menu") { - MenuProcessIncludes(e); + ProcessIncludes(e); } } } @@ -11059,27 +11072,28 @@ void MenuBase::MenuProcessIncludes(QDomElement &root) MenuBase::~MenuBase() { - if (m_menuDocument) + if (m_document) { - delete m_menuDocument; - m_menuDocument = NULL; + delete m_document; + m_document = NULL; } } -QDomElement MenuBase::MenuGetRoot(void) const +QDomElement MenuBase::GetRoot(void) const { - return m_menuDocument->documentElement(); + return m_document->documentElement(); } -QString MenuBase::MenuTranslate(const QString &text) const +QString MenuBase::Translate(const QString &text) const { return qApp->translate(m_translationContext, text.toUtf8(), NULL, QCoreApplication::UnicodeUTF8); } -bool MenuBase::MenuShowHelper(const QDomNode &node, - const QDomNode &selected, - bool doDisplay) +bool MenuBase::Show(const QDomNode &node, + const QDomNode &selected, + MenuItemDisplayer &displayer, + bool doDisplay) const { bool hasSelected = false; bool displayed = false; @@ -11093,8 +11107,7 @@ bool MenuBase::MenuShowHelper(const QDomNode &node, if (n.isElement()) { QDomElement e = n.toElement(); - QString text = e.attribute("text", ""); - text = MenuTranslate(text); + QString text = Translate(e.attribute("text", "")); QString show = e.attribute("show", ""); MenuShowContext showContext = (show == "active" ? kMenuShowActive : @@ -11103,23 +11116,24 @@ bool MenuBase::MenuShowHelper(const QDomNode &node, bool currentActive = (current == "active") && !hasSelected; if (e.tagName() == "menu") { - MenuItemContext c(n, text, (hasSelected && n == selected), + MenuItemContext c(*this, n, text, + (hasSelected && n == selected), doDisplay); - displayed |= MenuDisplayItem(c); + displayed |= displayer.MenuItemDisplay(c); } else if (e.tagName() == "item") { QString action = e.attribute("action", ""); - MenuItemContext c(n, showContext, currentActive, action, - text, doDisplay); - displayed |= MenuDisplayItem(c); + MenuItemContext c(*this, n, showContext, currentActive, + action, text, doDisplay); + displayed |= displayer.MenuItemDisplay(c); } else if (e.tagName() == "itemlist") { QString actiongroup = e.attribute("actiongroup", ""); - MenuItemContext c(n, showContext, currentActive, + MenuItemContext c(*this, n, showContext, currentActive, actiongroup, doDisplay); - displayed |= MenuDisplayItem(c); + displayed |= displayer.MenuItemDisplay(c); } } if (!doDisplay && displayed) @@ -11170,8 +11184,13 @@ static void addButton(const MenuItemContext &c, OSD *osd, bool active, (textInactive), (isMenu)) // Returns true if at least one item should be displayed. -bool TV::MenuDisplayItem(const MenuItemContext &c) +bool TV::MenuItemDisplay(const MenuItemContext &c) { + // Test &c.m_menu to determine which menu is being displayed and + // therefore which actions to test for. For the regular and + // compact playback menus, we do the same thing so no test is + // needed, but as other playback-context menus are added, we'll + // want to test. MenuCategory category = c.m_category; const QString &actionName = c.m_action; @@ -11183,11 +11202,11 @@ bool TV::MenuDisplayItem(const MenuItemContext &c) return result; if (category == kMenuCategoryMenu) { - result = MenuShowHelper(c.m_node, QDomNode(), false); + result = c.m_menu.Show(c.m_node, QDomNode(), *this, false); if (result && c.m_doDisplay) { QVariant v; - v.setValue(c.m_node); + v.setValue(MenuNodeTuple(c.m_menu, c.m_node)); osd->DialogAddButton(c.m_menuName, v, true, c.m_setCurrentActive); } return result; @@ -11809,7 +11828,7 @@ bool TV::MenuDisplayItem(const MenuItemContext &c) { BUTTON3(actionName, tr("Recorded Program"), "", true); QVariant v; - v.setValue(c.m_node); + v.setValue(MenuNodeTuple(c.m_menu, c.m_node)); m_tvm_jumprec_back_hack = v; } else if (actionName == "JUMPPREV") @@ -11890,10 +11909,10 @@ bool TV::MenuDisplayItem(const MenuItemContext &c) // Look in the specified keybinding context as well as the // Global context. QString text = GetMythMainWindow()-> - GetActionText(m_keyBindingContext, actionName); + GetActionText(c.m_menu.GetKeyBindingContext(), actionName); if (text.isEmpty()) - text = GetMythMainWindow() - ->GetActionText("Global", actionName); + text = GetMythMainWindow()-> + GetActionText("Global", actionName); if (!text.isEmpty()) BUTTON(actionName, text); } @@ -11912,7 +11931,7 @@ void TV::MenuLazyInit(void *field) } } -void TV::MenuInit(void) +void TV::PlaybackMenuInit(void) { m_tvmCtx = GetPlayerReadLock(-1, __FILE__, __LINE__); m_tvmOsd = GetOSDLock(m_tvmCtx); @@ -12058,7 +12077,7 @@ void TV::MenuInit(void) ctx->UnlockDeletePlayer(__FILE__, __LINE__); } -void TV::MenuDeinit(void) +void TV::PlaybackMenuDeinit(void) { ReturnOSDLock(m_tvmCtx, m_tvmOsd); ReturnPlayerLock(m_tvmCtx); @@ -12066,25 +12085,26 @@ void TV::MenuDeinit(void) m_tvmOsd = NULL; } -void TV::MenuShow(const QDomNode &node, const QDomNode &selected) +void TV::PlaybackMenuShow(const MenuBase &menu, + const QDomNode &node, const QDomNode &selected) { - MenuInit(); + PlaybackMenuInit(); if (m_tvmOsd) { - m_tvmOsd->DialogShow(OSD_DLG_MENU, m_menuName); - MenuBase::MenuShow(node, selected); + m_tvmOsd->DialogShow(OSD_DLG_MENU, menu.GetName()); + menu.Show(node, selected, *this); QString text = - MenuTranslate(node.toElement().attribute("text", m_menuName)); + menu.Translate(node.toElement().attribute("text", menu.GetName())); m_tvmOsd->DialogSetText(text); QDomNode parent = node.parentNode(); if (!parent.parentNode().isNull()) { QVariant v; - v.setValue(node); + v.setValue(MenuNodeTuple(menu, node)); m_tvmOsd->DialogBack("", v); } } - MenuDeinit(); + PlaybackMenuDeinit(); } void TV::MenuStrings(void) const @@ -12129,21 +12149,23 @@ void TV::MenuStrings(void) const void TV::ShowOSDMenu(const PlayerContext *ctx, bool isCompact) { - if (!MenuIsLoaded()) - { - MenuLoadFromFile("menu_playback.xml", - tr("Playback Menu"), - metaObject()->className(), - "TV Playback"); - m_compactMenu.MenuLoadFromFile("menu_playback_compact.xml", - tr("Playback Compact Menu"), - metaObject()->className(), - "TV Playback"); - } - if (isCompact && m_compactMenu.MenuIsLoaded()) - MenuShow(m_compactMenu.MenuGetRoot(), QDomNode()); - else if (MenuIsLoaded()) - MenuShow(MenuGetRoot(), QDomNode()); + if (!m_playbackMenu.IsLoaded()) + { + m_playbackMenu.Load("menu_playback.xml", + tr("Playback Menu"), + metaObject()->className(), + "TV Playback"); + m_compactMenu.Load("menu_playback_compact.xml", + tr("Playback Compact Menu"), + metaObject()->className(), + "TV Playback"); + } + if (isCompact && m_compactMenu.IsLoaded()) + PlaybackMenuShow(m_compactMenu, m_compactMenu.GetRoot(), + QDomNode()); + else if (m_playbackMenu.IsLoaded()) + PlaybackMenuShow(m_playbackMenu, m_playbackMenu.GetRoot(), + QDomNode()); } void TV::FillOSDMenuJumpRec(PlayerContext* ctx, const QString category, diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h index 43e7599aa4a..8bff8dc4e74 100644 --- a/mythtv/libs/libmythtv/tv_play.h +++ b/mythtv/libs/libmythtv/tv_play.h @@ -152,14 +152,18 @@ enum MenuShowContext { kMenuShowAlways }; +class MenuBase; + class MenuItemContext { public: // Constructor for a menu element. - MenuItemContext(const QDomNode &node, + MenuItemContext(const MenuBase &menu, + const QDomNode &node, const QString &menuName, bool setCurrentActive, bool doDisplay) : + m_menu(menu), m_node(node), m_category(kMenuCategoryMenu), m_menuName(menuName), @@ -169,12 +173,14 @@ class MenuItemContext m_actionText(""), m_doDisplay(doDisplay) {} // Constructor for an item element. - MenuItemContext(const QDomNode &node, + MenuItemContext(const MenuBase &menu, + const QDomNode &node, MenuShowContext showContext, bool setCurrentActive, const QString &action, const QString &actionText, bool doDisplay) : + m_menu(menu), m_node(node), m_category(kMenuCategoryItem), m_menuName(""), @@ -184,11 +190,13 @@ class MenuItemContext m_actionText(actionText), m_doDisplay(doDisplay) {} // Constructor for an itemlist element. - MenuItemContext(const QDomNode &node, + MenuItemContext(const MenuBase &menu, + const QDomNode &node, MenuShowContext showContext, bool setCurrentActive, const QString &action, bool doDisplay) : + m_menu(menu), m_node(node), m_category(kMenuCategoryItemlist), m_menuName(""), @@ -197,44 +205,53 @@ class MenuItemContext m_action(action), m_actionText(""), m_doDisplay(doDisplay) {} + const MenuBase &m_menu; const QDomNode &m_node; - MenuCategory m_category; - const QString m_menuName; + MenuCategory m_category; + const QString m_menuName; MenuShowContext m_showContext; - bool m_setCurrentActive; - const QString m_action; - const QString m_actionText; - bool m_doDisplay; + bool m_setCurrentActive; + const QString m_action; + const QString m_actionText; + bool m_doDisplay; +}; + +class MenuItemDisplayer +{ +public: + virtual bool MenuItemDisplay(const MenuItemContext &c) = 0; }; class MenuBase { public: - MenuBase() : m_menuDocument(NULL), m_translationContext(""), + MenuBase() : m_document(NULL), m_translationContext(""), m_recursionLevel(0) {} ~MenuBase(); - bool MenuLoadFromFile(const QString &filename, const QString &menuname, - const char *translationContext, - const QString &keyBindingContext); - bool MenuIsLoaded(void) const { return (m_menuDocument != NULL); } - QDomElement MenuGetRoot(void) const; - QString MenuTranslate(const QString &text) const; - virtual void MenuShow(const QDomNode &node, const QDomNode &selected) { - MenuShowHelper(node, selected, true); + bool Load(const QString &filename, + const QString &menuname, + const char *translationContext, + const QString &keyBindingContext); + bool IsLoaded(void) const { return (m_document != NULL); } + QDomElement GetRoot(void) const; + QString Translate(const QString &text) const; + bool Show(const QDomNode &node, const QDomNode &selected, + MenuItemDisplayer &displayer, + bool doDisplay = true) const; + QString GetName(void) const { return m_menuName; } + const char *GetTranslationContext(void) const { + return m_translationContext; + } + const QString &GetKeyBindingContext(void) const { + return m_keyBindingContext; } -protected: - virtual bool MenuShowHelper(const QDomNode &node, - const QDomNode &selected, - bool doDisplay); - virtual bool MenuDisplayItem(const MenuItemContext &c) { return false; } - virtual void MenuStrings(void) const {} - QDomDocument *m_menuDocument; - QString m_menuName; - const char *m_translationContext; - QString m_keyBindingContext; private: - void MenuProcessIncludes(QDomElement &root); - int m_recursionLevel; // guard against infinite recursion + void ProcessIncludes(QDomElement &root); + QDomDocument *m_document; + const char *m_translationContext; + QString m_menuName; + QString m_keyBindingContext; + int m_recursionLevel; // guard against infinite recursion }; /** @@ -255,7 +272,7 @@ class MenuBase * \qmlsignal TVPlaybackSought(qint position_seconds) * Absolute seek has completed to position_seconds */ -class MTV_PUBLIC TV : public QObject, public MenuBase +class MTV_PUBLIC TV : public QObject, public MenuItemDisplayer { friend class PlaybackBox; friend class GuideGrid; @@ -710,11 +727,12 @@ class MTV_PUBLIC TV : public QObject, public MenuBase void FillOSDMenuJumpRec (PlayerContext* ctx, const QString category = "", int level = 0, const QString selected = ""); - virtual void MenuShow(const QDomNode &node, const QDomNode &selected); - virtual bool MenuDisplayItem(const MenuItemContext &c); - virtual void MenuInit(void); - virtual void MenuDeinit(void); - virtual void MenuStrings(void) const; + void PlaybackMenuShow(const MenuBase &menu, + const QDomNode &node, const QDomNode &selected); + virtual bool MenuItemDisplay(const MenuItemContext &c); + void PlaybackMenuInit(void); + void PlaybackMenuDeinit(void); + void MenuStrings(void) const; void MenuLazyInit(void *field); // LCD @@ -1014,6 +1032,7 @@ class MTV_PUBLIC TV : public QObject, public MenuBase QVariant m_tvm_jumprec_back_hack; // End of playback menu state caching + MenuBase m_playbackMenu; MenuBase m_compactMenu; public: