Skip to content

Commit

Permalink
Merge pull request #9382 from tamland/context_menu_cleanup
Browse files Browse the repository at this point in the history
context menu cleanup after #9257
  • Loading branch information
tamland committed Mar 19, 2016
2 parents fa43177 + f53a9fb commit aea2d0b
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 151 deletions.
22 changes: 15 additions & 7 deletions xbmc/ContextMenuItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,15 @@ bool CContextMenuItem::IsGroup() const

bool CContextMenuItem::Execute(const CFileItemPtr& item) const
{
if (!item || !m_addon || m_library.empty() || IsGroup())
if (!item || m_library.empty() || IsGroup())
return false;

ADDON::AddonPtr addon;
if (!ADDON::CAddonMgr::GetInstance().GetAddon(m_addonId, addon))
return false;

LanguageInvokerPtr invoker(new CContextItemAddonInvoker(&g_pythonParser, item));
return (CScriptInvocationManager::GetInstance().ExecuteAsync(m_library, invoker, m_addon) != -1);
return (CScriptInvocationManager::GetInstance().ExecuteAsync(m_library, invoker, addon) != -1);
}

bool CContextMenuItem::operator==(const CContextMenuItem& other) const
Expand All @@ -61,34 +65,38 @@ bool CContextMenuItem::operator==(const CContextMenuItem& other) const
return (IsGroup() == other.IsGroup())
&& (m_parent == other.m_parent)
&& (m_library == other.m_library)
&& ((!m_addon && !other.m_addon) || (m_addon && other.m_addon && m_addon->ID() == other.m_addon->ID()));
&& (m_addonId == other.m_addonId);
}

std::string CContextMenuItem::ToString() const
{
if (IsGroup())
return StringUtils::Format("CContextMenuItem[group, id=%s, parent=%s, addon=%s]",
m_groupId.c_str(), m_parent.c_str(), m_addon ? m_addon->ID().c_str() : "null");
m_groupId.c_str(), m_parent.c_str(), m_addonId.c_str());
else
return StringUtils::Format("CContextMenuItem[item, parent=%s, library=%s, addon=%s]",
m_parent.c_str(), m_library.c_str(), m_addon ? m_addon->ID().c_str() : "null");
m_parent.c_str(), m_library.c_str(), m_addonId.c_str());
}

CContextMenuItem CContextMenuItem::CreateGroup(const std::string& label, const std::string& parent, const std::string& groupId)
CContextMenuItem CContextMenuItem::CreateGroup(const std::string& label, const std::string& parent,
const std::string& groupId, const std::string& addonId)
{
CContextMenuItem menuItem;
menuItem.m_label = label;
menuItem.m_parent = parent;
menuItem.m_groupId = groupId;
menuItem.m_addonId = addonId;
return menuItem;
}

CContextMenuItem CContextMenuItem::CreateItem(const std::string& label, const std::string& parent, const std::string& library, const INFO::InfoPtr& condition)
CContextMenuItem CContextMenuItem::CreateItem(const std::string& label, const std::string& parent,
const std::string& library, const INFO::InfoPtr& condition, const std::string& addonId)
{
CContextMenuItem menuItem;
menuItem.m_label = label;
menuItem.m_parent = parent;
menuItem.m_library = library;
menuItem.m_condition = condition;
menuItem.m_addonId = addonId;
return menuItem;
}
8 changes: 5 additions & 3 deletions xbmc/ContextMenuItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,15 @@ class CContextMenuItem : public IContextMenuItem
static CContextMenuItem CreateGroup(
const std::string& label,
const std::string& parent,
const std::string& groupId);
const std::string& groupId,
const std::string& addonId);

static CContextMenuItem CreateItem(
const std::string& label,
const std::string& parent,
const std::string& library,
const INFO::InfoPtr& condition);
const INFO::InfoPtr& condition,
const std::string& addonId);

friend class ADDON::CContextMenuAddon;

Expand All @@ -88,5 +90,5 @@ class CContextMenuItem : public IContextMenuItem
std::string m_groupId;
std::string m_library;
INFO::InfoPtr m_condition;
ADDON::AddonPtr m_addon;
std::string m_addonId; // The owner of this menu item
};
120 changes: 25 additions & 95 deletions xbmc/ContextMenuManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@

using namespace ADDON;

typedef std::pair<unsigned int, CContextMenuItem> Item;

const CContextMenuItem CContextMenuManager::MAIN = CContextMenuItem::CreateGroup("", "", "kodi.core.main");
const CContextMenuItem CContextMenuManager::MANAGE = CContextMenuItem::CreateGroup("", "", "kodi.core.manage");
const CContextMenuItem CContextMenuManager::MAIN = CContextMenuItem::CreateGroup("", "", "kodi.core.main", "");
const CContextMenuItem CContextMenuManager::MANAGE = CContextMenuItem::CreateGroup("", "", "kodi.core.manage", "");


CContextMenuManager::CContextMenuManager()
: m_nextButtonId(CONTEXT_BUTTON_FIRST_ADDON)
{
Init();
}
Expand Down Expand Up @@ -82,17 +80,9 @@ void CContextMenuManager::Register(const ContextItemAddonPtr& cm)
CSingleLock lock(m_criticalSection);
for (const auto& menuItem : cm->GetItems())
{
auto existing = std::find_if(m_addonItems.begin(), m_addonItems.end(),
[&](const Item& kv){ return kv.second == menuItem; });
if (existing != m_addonItems.end())
{
existing->second = menuItem;
}
else
{
m_addonItems.push_back(std::make_pair(m_nextButtonId, menuItem));
++m_nextButtonId;
}
auto it = std::find(m_addonItems.begin(), m_addonItems.end(), menuItem);
if (it == m_addonItems.end())
m_addonItems.push_back(menuItem);
}
}

Expand All @@ -106,11 +96,11 @@ bool CContextMenuManager::Unregister(const ContextItemAddonPtr& cm)
CSingleLock lock(m_criticalSection);

auto it = std::remove_if(m_addonItems.begin(), m_addonItems.end(),
[&](const Item& kv)
[&](const CContextMenuItem& item)
{
if (kv.second.IsGroup())
if (item.IsGroup())
return false; //keep in case other items use them
return std::find(menuItems.begin(), menuItems.end(), kv.second) != menuItems.end();
return std::find(menuItems.begin(), menuItems.end(), item) != menuItems.end();
}
);
m_addonItems.erase(it, m_addonItems.end());
Expand All @@ -127,86 +117,12 @@ bool CContextMenuManager::IsVisible(
{
CSingleLock lock(m_criticalSection);
return std::any_of(m_addonItems.begin(), m_addonItems.end(),
[&](const Item& kv){ return menuItem.IsParentOf(kv.second) && kv.second.IsVisible(fileItem); });
[&](const CContextMenuItem& other){ return menuItem.IsParentOf(other) && other.IsVisible(fileItem); });
}

return menuItem.IsVisible(fileItem);
}

void CContextMenuManager::AddVisibleItems(
const CFileItemPtr& fileItem, CContextButtons& list, const CContextMenuItem& root /* = CContextMenuItem::MAIN */) const
{
if (!fileItem)
return;

auto menuItems = GetAddonItemsWithId(*fileItem, root);
for (const auto& kv : menuItems)
list.emplace_back(kv.first, kv.second.GetLabel(*fileItem));
}

std::vector<std::pair<unsigned int, CContextMenuItem>> CContextMenuManager::GetAddonItemsWithId(
const CFileItem& fileItem, const CContextMenuItem& root /* = CContextMenuItem::MAIN */) const
{
using value_type = std::pair<unsigned int, CContextMenuItem>;
std::vector<value_type> result;

{
CSingleLock lock(m_criticalSection);
for (const auto& kv : m_addonItems)
if (IsVisible(kv.second, root, fileItem))
result.push_back(kv);
}

if (&root == &MAIN || &root == &MANAGE)
{
std::sort(result.begin(), result.end(),
[&](const value_type& lhs, const value_type& rhs)
{
return lhs.second.GetLabel(fileItem) < rhs.second.GetLabel(fileItem);
}
);
}
return result;
}

bool CContextMenuManager::OnClick(unsigned int id, const CFileItemPtr& item)
{
if (!item)
return false;

CSingleLock lock(m_criticalSection);

auto it = std::find_if(m_addonItems.begin(), m_addonItems.end(),
[id](const Item& kv){ return kv.first == id; });
if (it == m_addonItems.end())
{
CLog::Log(LOGERROR, "CContextMenuManager: unknown button id '%u'", id);
return false;
}

CContextMenuItem menuItem = it->second;
lock.Leave();
if (menuItem.IsGroup())
{
CLog::Log(LOGDEBUG, "CContextMenuManager: showing group '%s'", menuItem.ToString().c_str());
CContextButtons choices;
AddVisibleItems(item, choices, menuItem);
if (choices.empty())
{
CLog::Log(LOGERROR, "CContextMenuManager: no items in group '%s'", menuItem.ToString().c_str());
return false;
}
int choice = CGUIDialogContextMenu::ShowAndGetChoice(choices);
if (choice == -1)
return false;

return OnClick(choice, item);
}

return menuItem.Execute(item);
}


ContextMenuView CContextMenuManager::GetItems(const CFileItem& fileItem, const CContextMenuItem& root /*= MAIN*/) const
{
ContextMenuView result;
Expand All @@ -223,8 +139,22 @@ ContextMenuView CContextMenuManager::GetItems(const CFileItem& fileItem, const C
ContextMenuView CContextMenuManager::GetAddonItems(const CFileItem& fileItem, const CContextMenuItem& root /*= MAIN*/) const
{
ContextMenuView result;
for (const auto& kv : GetAddonItemsWithId(fileItem, root))
result.emplace_back(new CContextMenuItem(kv.second));
{
CSingleLock lock(m_criticalSection);
for (const auto& menu : m_addonItems)
if (IsVisible(menu, root, fileItem))
result.emplace_back(new CContextMenuItem(menu));
}

if (&root == &MAIN || &root == &MANAGE)
{
std::sort(result.begin(), result.end(),
[&](const ContextMenuView::value_type& lhs, const ContextMenuView::value_type& rhs)
{
return lhs->GetLabel(fileItem) < rhs->GetLabel(fileItem);
}
);
}
return result;
}

Expand Down
27 changes: 1 addition & 26 deletions xbmc/ContextMenuManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,6 @@ class CContextMenuManager

ContextMenuView GetAddonItems(const CFileItem& item, const CContextMenuItem& root = MAIN) const;

/*!
* Deprecated.
* \param id - id of the context button clicked on.
* \param item - the selected file item.
* \return true on success, otherwise false.
*/
bool OnClick(unsigned int id, const CFileItemPtr& item);

/*!
* Deprecated.
* \brief Adds all registered context item to the list.
* \param item - the currently selected item.
* \param list - the context menu.
* \param root - the context menu responsible for this call.
*/
void AddVisibleItems(
const CFileItemPtr& item,
CContextButtons& list,
const CContextMenuItem& root = MAIN) const;

/*!
* \brief Adds a context item to this manager.
* NOTE: only 'enabled' context addons should be added.
Expand All @@ -84,14 +64,9 @@ class CContextMenuManager
const CContextMenuItem& root,
const CFileItem& fileItem) const;

/*! Deprecated. */
std::vector<std::pair<unsigned int, CContextMenuItem>> GetAddonItemsWithId(const CFileItem& fileItem,
const CContextMenuItem& root = CContextMenuManager::MAIN) const;

CCriticalSection m_criticalSection;
std::vector<std::pair<unsigned int, CContextMenuItem>> m_addonItems;
std::vector<CContextMenuItem> m_addonItems;
std::vector<std::shared_ptr<IContextMenuItem>> m_items;
unsigned int m_nextButtonId;
};

namespace CONTEXTMENU
Expand Down
14 changes: 5 additions & 9 deletions xbmc/addons/ContextMenuAddon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void CContextMenuAddon::ParseMenu(
menuId = ss.str();
}

items.push_back(CContextMenuItem::CreateGroup(menuLabel, parent, menuId));
items.push_back(CContextMenuItem::CreateGroup(menuLabel, parent, menuId, props.id));

ELEMENTS subMenus;
if (CAddonMgr::GetInstance().GetExtElements(elem, "menu", subMenus))
Expand All @@ -73,7 +73,7 @@ void CContextMenuAddon::ParseMenu(
if (!label.empty() && !library.empty() && !visCondition.empty())
{
auto menu = CContextMenuItem::CreateItem(label, menuId,
URIUtils::AddFileToFolder(props.path, library), g_infoManager.Register(visCondition, 0));
URIUtils::AddFileToFolder(props.path, library), g_infoManager.Register(visCondition, 0), props.id);
items.push_back(menu);
}
}
Expand Down Expand Up @@ -111,7 +111,7 @@ std::unique_ptr<CContextMenuAddon> CContextMenuAddon::FromExtension(AddonProps p

CContextMenuItem menuItem = CContextMenuItem::CreateItem(label, parent,
URIUtils::AddFileToFolder(props.path, props.libname),
g_infoManager.Register(visCondition, 0));
g_infoManager.Register(visCondition, 0), props.id);

items.push_back(menuItem);
}
Expand All @@ -125,13 +125,9 @@ CContextMenuAddon::CContextMenuAddon(AddonProps props, std::vector<CContextMenuI
{
}

std::vector<CContextMenuItem> CContextMenuAddon::GetItems()
std::vector<CContextMenuItem> CContextMenuAddon::GetItems() const
{
//Return a copy which owns `this`
std::vector<CContextMenuItem> ret = m_items;
for (CContextMenuItem& menuItem : ret)
menuItem.m_addon = this->shared_from_this();
return ret;
return m_items;
}

}
4 changes: 2 additions & 2 deletions xbmc/addons/ContextMenuAddon.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace ADDON
explicit CContextMenuAddon(AddonProps props) : CAddon(std::move(props)) {}
CContextMenuAddon(AddonProps props, std::vector<CContextMenuItem> items);

std::vector<CContextMenuItem> GetItems();
std::vector<CContextMenuItem> GetItems() const;

private:
static void ParseMenu(const AddonProps& props, cp_cfg_element_t* elem, const std::string& parent,
Expand All @@ -46,5 +46,5 @@ namespace ADDON
std::vector<CContextMenuItem> m_items;
};

typedef std::shared_ptr<CContextMenuAddon> ContextItemAddonPtr;
typedef std::shared_ptr<const CContextMenuAddon> ContextItemAddonPtr;
}
4 changes: 0 additions & 4 deletions xbmc/dialogs/GUIDialogContextMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,6 @@ enum CONTEXT_BUTTON { CONTEXT_BUTTON_CANCELLED = 0,
CONTEXT_BUTTON_USER8,
CONTEXT_BUTTON_USER9,
CONTEXT_BUTTON_USER10,

//NOTE: this has to be the last in this enum,
//because this one, and the ones higher will be used by context addons
CONTEXT_BUTTON_FIRST_ADDON
};

class CContextButtons : public std::vector< std::pair<unsigned int, std::string> >
Expand Down
11 changes: 8 additions & 3 deletions xbmc/dialogs/GUIDialogFavourites.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ void CGUIDialogFavourites::OnPopupMenu(int item)
choices.Add(5, 20019);

CFileItemPtr itemPtr = m_favourites->Get(item);
CContextMenuManager::GetInstance().AddVisibleItems(itemPtr, choices);

//temporary workaround until the context menu ids are removed
const int addonItemOffset = 10000;
auto addonItems = CContextMenuManager::GetInstance().GetAddonItems(*itemPtr);
for (int i = 0; i < addonItems.size(); ++i)
choices.Add(addonItemOffset + i, addonItems[i]->GetLabel(*itemPtr));

int button = CGUIDialogContextMenu::ShowAndGetChoice(choices);

Expand All @@ -150,8 +155,8 @@ void CGUIDialogFavourites::OnPopupMenu(int item)
OnRename(item);
else if (button == 5)
OnSetThumb(item);
else if (button >= CONTEXT_BUTTON_FIRST_ADDON)
CContextMenuManager::GetInstance().OnClick(button, itemPtr);
else if (button >= addonItemOffset)
CONTEXTMENU::LoopFrom(*addonItems.at(button - addonItemOffset), itemPtr);
}

void CGUIDialogFavourites::OnMoveItem(int item, int amount)
Expand Down
Loading

0 comments on commit aea2d0b

Please sign in to comment.