Skip to content

Commit

Permalink
Updated Python plug-in API to support adding dividers to menu entries.
Browse files Browse the repository at this point in the history
  • Loading branch information
ggarra13 committed Oct 9, 2023
1 parent bb93887 commit 55264ca
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 14 deletions.
35 changes: 32 additions & 3 deletions mrv2/lib/mrvPy/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,44 @@ namespace mrv
void run_python_method_cb(Fl_Menu_* m, void* d)
{
ViewerUI* ui = App::ui;
py::handle func = *(static_cast<py::handle*>(d));
const py::handle& obj = *(static_cast<py::handle*>(d));
try
{
PyStdErrOutStreamRedirect pyRedirect;
func();
if (py::isinstance<py::function>(obj))
{
// obj is a Python function
py::function func = py::reinterpret_borrow<py::function>(obj);
func();
}
else if (py::isinstance<py::tuple>(obj))
{
// obj is a Python tuple
py::tuple tup = py::reinterpret_borrow<py::tuple>(obj);
if (tup.size() == 2 && py::isinstance<py::function>(tup[0]) &&
py::isinstance<py::str>(tup[1]))
{
py::function func(tup[0]);
py::str str(tup[1]);
func();
}
else
{
throw std::runtime_error(
_("Expected a tuple containing a Python function and a "
"string with menu options in it."));
}
}
else
{
throw std::runtime_error(
_("Expected a handle to a Python function or to a tuple "
"containing a Python function and a "
"string with menu options in it."));
}

const std::string& out = pyRedirect.stdoutString();
const std::string& err = pyRedirect.stderrString();

if (!out.empty() || !err.empty())
{
if (!pythonPanel)
Expand Down
44 changes: 35 additions & 9 deletions mrv2/lib/mrvUI/mrvMenus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// mrv2
// Copyright Contributors to the mrv2 Project. All rights reserved.

#include <tlCore/StringFormat.h>

#include "mrvCore/mrvI8N.h"
#include "mrvCore/mrvHotkey.h"
#include "mrvCore/mrvMath.h"
Expand Down Expand Up @@ -1132,26 +1134,50 @@ namespace mrv
}

#ifdef MRV2_PYBIND11
idx = -1;
for (const auto& entry : pythonMenus)
{
if (entry == "__divider__")
int mode = 0;
const py::handle& obj = pythonMenus.at(entry);
if (!py::isinstance<py::function>(obj) &&
!py::isinstance<py::tuple>(obj))
{
if (idx < 0)
std::string msg =
string::Format(_("In '{0}' expected a function as a value "
"or a tuple containing a Python function "
"and a string with menu options in it."))
.arg(entry);
LOG_ERROR(msg);
continue;
}
if (py::isinstance<py::tuple>(obj))
{
// obj is a Python tuple
py::tuple tup = py::reinterpret_borrow<py::tuple>(obj);
if (tup.size() == 2 && py::isinstance<py::function>(tup[0]) &&
py::isinstance<py::str>(tup[1]))
{
LOG_ERROR(
_("__divider__ cannot be the first item in the menu."));
py::str str(tup[1]);
const std::string modes = str.cast<std::string>();
if (modes.find("__divider__") != std::string::npos)
{
mode |= FL_MENU_DIVIDER;
}
}
else
{
item = (Fl_Menu_Item*)&(menu->menu()[idx]);
item->flags |= FL_MENU_DIVIDER;
std::string msg =
string::Format(
_("In '{0}' expected a function a tuple "
"containing a Python function and a string "
"with menu options in it."))
.arg(entry);
LOG_ERROR(msg);
continue;
}
continue;
}
idx = menu->add(
entry.c_str(), 0, (Fl_Callback*)run_python_method_cb,
(void*)&pythonMenus.at(entry));
(void*)&pythonMenus.at(entry), mode);
}
#endif

Expand Down
8 changes: 6 additions & 2 deletions mrv2/python/plug-ins/mrv2_hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ def run(self):
Returns:
dict: a dictionary of key for menu entries and values as methods.
The value can be a tuple to add options like a divider for a menu
entry.
"""
def menus(self):
menus = {
Expand Down Expand Up @@ -83,11 +85,13 @@ def play(self):
Returns:
dict: a dictionary of key for menu entries and values as methods.
The value can be a tuple to add options like a divider for a menu
entry.
"""
def menus(self):
menus = {
"Python/Play/Forwards" : self.play, # call a method
"__divider__" : None, # add a divider
# Call a method and place a divider line after the menu
"Python/Play/Forwards" : (self.play, '__divider__'),
"Python/Play/Backwards" : timeline.playBackwards # call a function
}
return menus
Expand Down

0 comments on commit 55264ca

Please sign in to comment.