7#include <QtCore/qobject.h>
8#include <QtCore/qlist.h>
9#include <QtGui/qicon.h>
10#include <QtGui/qwindow.h>
14#include <qpa/qplatformtheme.h>
24 QtOhos::
JsState &jsState, QOhosConsumer<std::string> clickedMenuCodeConsumer)
26 return registerQOhosOnOffMethodsBasedEventHandler(
27 jsState.eval<QNapi::Object>(
"@kit.StatusBarExtensionKit.statusBarManager"),
29 [clickedMenuCodeConsumer = std::move(clickedMenuCodeConsumer)](
const QtOhos::
CallbackInfo &info) {
30 auto eventData = info.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
31 auto optMenuCode = QNapi::getOptionalPropOrEmpty<QNapi::String>(
32 QNapi::getOptionalPropOrEmpty<QNapi::Object>(eventData,
"data"),
34 if (!optMenuCode.IsEmpty()) {
35 clickedMenuCodeConsumer(optMenuCode);
38 "%s: no 'menuCode' in the event (%s), ignoring it",
39 Q_FUNC_INFO, QNapi::toJsonString(eventData).c_str());
45 QtOhos::
JsState &jsState,
const QIcon &icon,
const QSize &iconSize)
50 QImage iconImage = icon.pixmap(iconSize).toImage();
51 if (iconImage.isNull())
54 auto *env = jsState.env();
56 makeDisplayDensityScaledJsPixelMapFromQImage(jsState, iconImage);
58 auto imageSize = menuIcon.eval<QNapi::Object>(
"getImageInfoSync().size");
60 int imageWidth = imageSize.get<QNapi::Number>(
"width");
61 int imageHeight = imageSize.get<QNapi::Number>(
"height");
62 qOhosPrintfDebug(
"%s: created PixelMap size: %dx%d", Q_FUNC_INFO, imageWidth, imageHeight);
64 return QNapi::makeObject(
73 QtOhos::
JsState &jsState,
const QIcon &icon,
const QSize &iconSize)
75 auto itemIcon = makeJsStatusBarItemIcon(jsState, icon, iconSize);
79 return QNapi::makeObject(
89 return QNapi::makeObject(
92 {
"abilityName",
"invalidAbility"},
94 {
"menuCode", menuCode},
100 const QIcon &icon,
const QSize &iconSize)
102 auto statusBarMenuItem = QNapi::makeObject(
106 {
"menuAction", makeNotifyOnlyJsStatusBarMenuAction(jsState, menuCode)},
109 if (
auto options = makeJsStatusBarMenuItemOptions(jsState, icon, iconSize))
110 statusBarMenuItem.set(
"options", *options);
112 return statusBarMenuItem;
116 QtOhos::
JsState &jsState,
const std::string &title, QNapi::Array jsStatusBarSubMenuItems,
117 const QIcon &icon,
const QSize &iconSize)
119 auto statusBarMenuItem = QNapi::makeObject(
123 {
"subMenu", jsStatusBarSubMenuItems},
126 if (
auto options = makeJsStatusBarMenuItemOptions(jsState, icon, iconSize))
127 statusBarMenuItem.set(
"options", *options);
129 return statusBarMenuItem;
134 const QIcon &icon,
const QSize &iconSize)
136 auto statusBarSubMenuItem = QNapi::makeObject(
139 {
"subTitle", subTitle},
140 {
"menuAction", makeNotifyOnlyJsStatusBarMenuAction(jsState, menuCode)},
143 if (
auto options = makeJsStatusBarMenuItemOptions(jsState, icon, iconSize))
144 statusBarSubMenuItem.set(
"options", *options);
146 return statusBarSubMenuItem;
181 std::string m_menuCode;
183 bool m_isSeparator =
false;
186 static std::string generateNextMenuCode();
196 void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
override;
206 void showPopup(
const QWindow *parentWindow,
const QRect &targetRect,
const QPlatformMenuItem *item)
override;
220 QPlatformMenuItem *findItemByMenuCode(
const std::string &menuCode)
const;
221 void handleRightClickEvent(
const std::string &menuCode);
224 QList<QPlatformMenuItem *> m_menuItems;
228 std::shared_ptr<
void> m_rightMenuClickListenerHandle;
231 std::shared_ptr<JsScopeData> m_jsScopeData;
235 : QPlatformMenuItem()
236 , m_menuCode(generateNextMenuCode())
258 if (menu !=
nullptr && ohosMenu ==
nullptr)
259 qOhosPrintfWarning(
"%s: got menu object of incompatible type", Q_FUNC_INFO);
271 m_isSeparator = isSeparator;
318 return std::optional<QNapi::Object>();
322 auto title = QPlatformTheme::removeMnemonics(m_text).toStdString();
324 if (m_menu ==
nullptr) {
325 return [title, menuCode = m_menuCode, icon = m_icon](
QtOhos::
JsState &jsState) {
326 return std::optional(
327 makeJsStatusBarMenuItemWithAction(
328 jsState, title, menuCode, icon, defaultStatusBarMenuItemIconSize));
331 return [title, jsSubMenuItemsFactory = m_menu->makeJsStatusBarSubMenuItemsFactory(),
333 return std::optional(
334 makeJsStatusBarMenuItemWithSubMenu(
335 jsState, title, jsSubMenuItemsFactory(jsState), icon, defaultStatusBarMenuItemIconSize));
344 "%s: separator item %p used in sub-menu, which is unsupported on OHOS, ignoring",
347 return std::optional<QNapi::Object>();
351 if (m_menu !=
nullptr) {
353 "%s: nested-menu item %p used in sub-menu, which is unsupported on OHOS, ignoring",
356 return std::optional<QNapi::Object>();
360 auto subTitle = QPlatformTheme::removeMnemonics(m_text).toStdString();
362 return [subTitle, menuCode = m_menuCode, icon = m_icon](
QtOhos::
JsState &jsState) {
363 return std::optional(
364 makeJsStatusBarSubMenuItem(
365 jsState, subTitle, menuCode, icon, defaultStatusBarMenuItemIconSize));
371 static std::atomic<
std::uint64_t> menuCodeCounter(0);
373 auto counterValue = ++menuCodeCounter;
374 return std::to_string(counterValue);
380 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
381 m_jsScopeData = QtOhos::evalInJsThread(
382 [&](QtOhos::JsState &jsState) {
383 return QtOhos::makeProxyWithJsThreadDeleter(
384 QtOhos::moveToSharedPtr(
386 .m_rightMenuClickListenerHandle = registerOhosRightMenuClickListener(
388 [selfRef](std::string menuCode) {
389 selfRef.visitInQtThreadIfAlive(
390 [menuCode](
auto &self) {
391 self.handleRightClickEvent(menuCode);
401 if (menuItem ==
nullptr)
404 if (before ==
nullptr) {
405 m_menuItems.append(menuItem);
409 const int idx = m_menuItems.indexOf(before);
411 m_menuItems.insert(idx, menuItem);
413 m_menuItems.append(menuItem);
418 if (menuItem ==
nullptr)
420 m_menuItems.removeAll(menuItem);
455 Q_UNUSED(parentWindow);
456 Q_UNUSED(targetRect);
466 if (position < 0 || position >= m_menuItems.size())
468 return m_menuItems.at(position);
473 for (
auto *item : m_menuItems) {
474 if (item && item->tag() == tag)
492 std::vector<std::function<std::optional<QNapi::Object>(QtOhos::JsState &)>> jsMenuItemsFactories;
493 for (
auto *item : m_menuItems) {
494 auto *ohosItem = qobject_cast<QOhosStatusBarMenuItem *>(item);
495 jsMenuItemsFactories.push_back(
497 ? ohosItem->makeJsStatusBarMenuItemFactory()
498 : [](QtOhos::JsState &) {
499 return std::optional<QNapi::Object>();
503 return [jsMenuItemsFactories = std::move(jsMenuItemsFactories)](
QtOhos::
JsState &jsState) {
504 std::vector<QNapi::ValueWrapper> jsGroupMenusArray;
506 std::vector<QNapi::ValueWrapper> currentJsMenuItemsArray;
508 for (
const auto &jsMenuItemFactory : jsMenuItemsFactories) {
509 std::optional<QNapi::Object> optJsMenuItem = jsMenuItemFactory(jsState);
510 if (optJsMenuItem.has_value()) {
511 currentJsMenuItemsArray.push_back(optJsMenuItem.value());
513 jsGroupMenusArray.push_back(QNapi::makeArray(jsState.env(), currentJsMenuItemsArray));
514 currentJsMenuItemsArray.clear();
518 jsGroupMenusArray.push_back(QNapi::makeArray(jsState.env(), currentJsMenuItemsArray));
519 currentJsMenuItemsArray.clear();
521 return QNapi::makeArray(jsState.env(), jsGroupMenusArray);
527 std::vector<std::function<std::optional<QNapi::Object>(QtOhos::JsState &)>> jsSubMenuItemsFactories;
528 for (
auto *item : m_menuItems) {
529 auto *ohosItem = qobject_cast<QOhosStatusBarMenuItem *>(item);
530 if (ohosItem !=
nullptr)
531 jsSubMenuItemsFactories.push_back(ohosItem->makeJsStatusBarSubMenuItemFactory());
534 return [jsSubMenuItemsFactories = std::move(jsSubMenuItemsFactories)](
QtOhos::
JsState &jsState) {
535 std::vector<QNapi::ValueWrapper> jsSubMenuItems;
536 for (
const auto &jsSubMenuItemsFactory : jsSubMenuItemsFactories) {
537 std::optional<QNapi::Object> optJsSubMenuItem = jsSubMenuItemsFactory(jsState);
538 if (optJsSubMenuItem.has_value())
539 jsSubMenuItems.push_back(optJsSubMenuItem.value());
541 return QNapi::makeArray(jsState.env(), jsSubMenuItems);
547 for (
auto *item : m_menuItems) {
548 auto *ohosItem = qobject_cast<QOhosStatusBarMenuItem *>(item);
549 if (ohosItem !=
nullptr && ohosItem->menuCode() == menuCode)
557 QPlatformMenuItem *item = findItemByMenuCode(menuCode);
558 if (item ==
nullptr) {
559 qOhosPrintfWarning(
"%s: Menu item with code '%s' not found", Q_FUNC_INFO, menuCode.c_str());
564 if (ohosItem !=
nullptr)
565 Q_EMIT ohosItem->activated();
579#include "qohosstatusbarmenu.moc"
Combined button and popup list for selecting options.
std::optional< QNapi::Object > makeJsStatusBarMenuItemOptions(QtOhos::JsState &jsState, const QIcon &icon, const QSize &iconSize)
QNapi::Object makeJsStatusBarMenuItemWithSubMenu(QtOhos::JsState &jsState, const std::string &title, QNapi::Array jsStatusBarSubMenuItems, const QIcon &icon, const QSize &iconSize)
QNapi::Object makeNotifyOnlyJsStatusBarMenuAction(QtOhos::JsState &jsState, const std::string &menuCode)
QNapi::Object makeJsStatusBarMenuItemWithAction(QtOhos::JsState &jsState, const std::string &title, const std::string &menuCode, const QIcon &icon, const QSize &iconSize)
std::optional< QNapi::Object > makeJsStatusBarItemIcon(QtOhos::JsState &jsState, const QIcon &icon, const QSize &iconSize)
std::shared_ptr< void > registerOhosRightMenuClickListener(QtOhos::JsState &jsState, QOhosConsumer< std::string > clickedMenuCodeConsumer)
constexpr QSize defaultStatusBarMenuItemIconSize(48, 48)
QNapi::Object makeJsStatusBarSubMenuItem(QtOhos::JsState &jsState, const std::string &subTitle, const std::string &menuCode, const QIcon &icon, const QSize &iconSize)