7#include <QtCore/qobject.h>
8#include <QtCore/qlist.h>
9#include <QtGui/qicon.h>
10#include <QtGui/qwindow.h>
14#include <qohosjsscopedataowner.h>
15#include <qpa/qplatformtheme.h>
25 QOhosJsState &jsState, QOhosConsumer<std::string> clickedMenuCodeConsumer)
27 return registerQOhosOnOffMethodsBasedEventHandler(
28 jsState.eval<QNapi::Object>(
"@kit.StatusBarExtensionKit.statusBarManager"),
30 [clickedMenuCodeConsumer = std::move(clickedMenuCodeConsumer)](
const QOhosCallbackInfo &info) {
31 auto eventData = info.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
32 auto optMenuCode = QNapi::getOptionalPropOrEmpty<QNapi::String>(
33 QNapi::getOptionalPropOrEmpty<QNapi::Object>(eventData,
"data"),
35 if (!optMenuCode.IsEmpty()) {
36 clickedMenuCodeConsumer(optMenuCode);
39 "%s: no 'menuCode' in the event (%s), ignoring it",
40 Q_FUNC_INFO, QNapi::toJsonString(eventData).c_str());
46 QOhosJsState &jsState,
const QIcon &icon,
const QSize &iconSize)
51 QImage iconImage = icon.pixmap(iconSize).toImage();
52 if (iconImage.isNull())
55 auto *env = jsState.env();
57 makeDisplayDensityScaledJsPixelMapFromQImage(jsState, iconImage);
59 auto imageSize = menuIcon.eval<QNapi::Object>(
"getImageInfoSync().size");
61 int imageWidth = imageSize.get<QNapi::Number>(
"width");
62 int imageHeight = imageSize.get<QNapi::Number>(
"height");
63 qOhosPrintfDebug(
"%s: created PixelMap size: %dx%d", Q_FUNC_INFO, imageWidth, imageHeight);
65 return QNapi::makeObject(
74 QOhosJsState &jsState,
const QIcon &icon,
const QSize &iconSize)
76 auto itemIcon = makeJsStatusBarItemIcon(jsState, icon, iconSize);
80 return QNapi::makeObject(
88 QOhosJsState &jsState,
const std::string &menuCode)
90 return QNapi::makeObject(
93 {
"abilityName",
"invalidAbility"},
95 {
"menuCode", menuCode},
100 QOhosJsState &jsState,
const std::string &title,
const std::string &menuCode,
101 const QIcon &icon,
const QSize &iconSize)
103 auto statusBarMenuItem = QNapi::makeObject(
107 {
"menuAction", makeNotifyOnlyJsStatusBarMenuAction(jsState, menuCode)},
110 if (
auto options = makeJsStatusBarMenuItemOptions(jsState, icon, iconSize))
111 statusBarMenuItem.set(
"options", *options);
113 return statusBarMenuItem;
117 QOhosJsState &jsState,
const std::string &title, QNapi::Array jsStatusBarSubMenuItems,
118 const QIcon &icon,
const QSize &iconSize)
120 auto statusBarMenuItem = QNapi::makeObject(
124 {
"subMenu", jsStatusBarSubMenuItems},
127 if (
auto options = makeJsStatusBarMenuItemOptions(jsState, icon, iconSize))
128 statusBarMenuItem.set(
"options", *options);
130 return statusBarMenuItem;
134 QOhosJsState &jsState,
const std::string &subTitle,
const std::string &menuCode,
135 const QIcon &icon,
const QSize &iconSize)
137 auto statusBarSubMenuItem = QNapi::makeObject(
140 {
"subTitle", subTitle},
141 {
"menuAction", makeNotifyOnlyJsStatusBarMenuAction(jsState, menuCode)},
144 if (
auto options = makeJsStatusBarMenuItemOptions(jsState, icon, iconSize))
145 statusBarSubMenuItem.set(
"options", *options);
147 return statusBarSubMenuItem;
182 std::string m_menuCode;
184 bool m_isSeparator =
false;
187 static std::string generateNextMenuCode();
197 void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
override;
207 void showPopup(
const QWindow *parentWindow,
const QRect &targetRect,
const QPlatformMenuItem *item)
override;
221 QPlatformMenuItem *findItemByMenuCode(
const std::string &menuCode)
const;
222 void handleRightClickEvent(
const std::string &menuCode);
225 QList<QPlatformMenuItem *> m_menuItems;
229 std::shared_ptr<
void> m_rightMenuClickListenerHandle;
236 : QPlatformMenuItem()
237 , m_menuCode(generateNextMenuCode())
259 if (menu !=
nullptr && ohosMenu ==
nullptr)
260 qOhosPrintfWarning(
"%s: got menu object of incompatible type", Q_FUNC_INFO);
272 m_isSeparator = isSeparator;
318 return [](QOhosJsState &) {
319 return std::optional<QNapi::Object>();
323 auto title = QPlatformTheme::removeMnemonics(m_text).toStdString();
325 if (m_menu ==
nullptr) {
326 return [title, menuCode = m_menuCode, icon = m_icon](QOhosJsState &jsState) {
327 return std::optional(
328 makeJsStatusBarMenuItemWithAction(
329 jsState, title, menuCode, icon, defaultStatusBarMenuItemIconSize));
332 return [title, jsSubMenuItemsFactory = m_menu->makeJsStatusBarSubMenuItemsFactory(),
333 icon = m_icon](QOhosJsState &jsState) {
334 return std::optional(
335 makeJsStatusBarMenuItemWithSubMenu(
336 jsState, title, jsSubMenuItemsFactory(jsState), icon, defaultStatusBarMenuItemIconSize));
345 "%s: separator item %p used in sub-menu, which is unsupported on OHOS, ignoring",
347 return [](QOhosJsState &) {
348 return std::optional<QNapi::Object>();
352 if (m_menu !=
nullptr) {
354 "%s: nested-menu item %p used in sub-menu, which is unsupported on OHOS, ignoring",
356 return [](QOhosJsState &) {
357 return std::optional<QNapi::Object>();
361 auto subTitle = QPlatformTheme::removeMnemonics(m_text).toStdString();
363 return [subTitle, menuCode = m_menuCode, icon = m_icon](QOhosJsState &jsState) {
364 return std::optional(
365 makeJsStatusBarSubMenuItem(
366 jsState, subTitle, menuCode, icon, defaultStatusBarMenuItemIconSize));
372 static std::atomic<
std::uint64_t> menuCodeCounter(0);
374 auto counterValue = ++menuCodeCounter;
375 return std::to_string(counterValue);
379 : QOhosStatusBarMenu()
381 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
382 QOhosJsThreadGateway::runAndWait(
383 [&](QOhosJsState &jsState) {
384 *m_jsScopeData = JsScopeData {
385 .m_rightMenuClickListenerHandle = registerOhosRightMenuClickListener(
387 [selfRef](std::string menuCode) {
388 selfRef.visitInQtThreadIfAlive(
389 [menuCode](
auto &self) {
390 self.handleRightClickEvent(menuCode);
400 if (menuItem ==
nullptr)
403 if (before ==
nullptr) {
404 m_menuItems.append(menuItem);
408 const int idx = m_menuItems.indexOf(before);
410 m_menuItems.insert(idx, menuItem);
412 m_menuItems.append(menuItem);
417 if (menuItem ==
nullptr)
419 m_menuItems.removeAll(menuItem);
454 Q_UNUSED(parentWindow);
455 Q_UNUSED(targetRect);
465 if (position < 0 || position >= m_menuItems.size())
467 return m_menuItems.at(position);
472 for (
auto *item : m_menuItems) {
473 if (item && item->tag() == tag)
491 std::vector<std::function<std::optional<QNapi::Object>(QOhosJsState &)>> jsMenuItemsFactories;
492 for (
auto *item : m_menuItems) {
493 auto *ohosItem = qobject_cast<QOhosStatusBarMenuItem *>(item);
494 jsMenuItemsFactories.push_back(
496 ? ohosItem->makeJsStatusBarMenuItemFactory()
497 : [](QOhosJsState &) {
498 return std::optional<QNapi::Object>();
502 return [jsMenuItemsFactories = std::move(jsMenuItemsFactories)](QOhosJsState &jsState) {
503 std::vector<QNapi::ValueWrapper> jsGroupMenusArray;
505 std::vector<QNapi::ValueWrapper> currentJsMenuItemsArray;
507 for (
const auto &jsMenuItemFactory : jsMenuItemsFactories) {
508 std::optional<QNapi::Object> optJsMenuItem = jsMenuItemFactory(jsState);
509 if (optJsMenuItem.has_value()) {
510 currentJsMenuItemsArray.push_back(optJsMenuItem.value());
512 jsGroupMenusArray.push_back(QNapi::makeArray(jsState.env(), currentJsMenuItemsArray));
513 currentJsMenuItemsArray.clear();
517 jsGroupMenusArray.push_back(QNapi::makeArray(jsState.env(), currentJsMenuItemsArray));
518 currentJsMenuItemsArray.clear();
520 return QNapi::makeArray(jsState.env(), jsGroupMenusArray);
526 std::vector<std::function<std::optional<QNapi::Object>(QOhosJsState &)>> jsSubMenuItemsFactories;
527 for (
auto *item : m_menuItems) {
528 auto *ohosItem = qobject_cast<QOhosStatusBarMenuItem *>(item);
529 if (ohosItem !=
nullptr)
530 jsSubMenuItemsFactories.push_back(ohosItem->makeJsStatusBarSubMenuItemFactory());
533 return [jsSubMenuItemsFactories = std::move(jsSubMenuItemsFactories)](QOhosJsState &jsState) {
534 std::vector<QNapi::ValueWrapper> jsSubMenuItems;
535 for (
const auto &jsSubMenuItemsFactory : jsSubMenuItemsFactories) {
536 std::optional<QNapi::Object> optJsSubMenuItem = jsSubMenuItemsFactory(jsState);
537 if (optJsSubMenuItem.has_value())
538 jsSubMenuItems.push_back(optJsSubMenuItem.value());
540 return QNapi::makeArray(jsState.env(), jsSubMenuItems);
546 for (
auto *item : m_menuItems) {
547 auto *ohosItem = qobject_cast<QOhosStatusBarMenuItem *>(item);
548 if (ohosItem !=
nullptr && ohosItem->menuCode() == menuCode)
556 QPlatformMenuItem *item = findItemByMenuCode(menuCode);
557 if (item ==
nullptr) {
558 qOhosPrintfWarning(
"%s: Menu item with code '%s' not found", Q_FUNC_INFO, menuCode.c_str());
563 if (ohosItem !=
nullptr)
564 Q_EMIT ohosItem->activated();
569QOhosStatusBarMenu::QOhosStatusBarMenu() =
default;
578#include "qohosstatusbarmenu.moc"
Combined button and popup list for selecting options.
QNapi::Object makeJsStatusBarSubMenuItem(QOhosJsState &jsState, const std::string &subTitle, const std::string &menuCode, const QIcon &icon, const QSize &iconSize)
QNapi::Object makeNotifyOnlyJsStatusBarMenuAction(QOhosJsState &jsState, const std::string &menuCode)
QNapi::Object makeJsStatusBarMenuItemWithSubMenu(QOhosJsState &jsState, const std::string &title, QNapi::Array jsStatusBarSubMenuItems, const QIcon &icon, const QSize &iconSize)
std::optional< QNapi::Object > makeJsStatusBarItemIcon(QOhosJsState &jsState, const QIcon &icon, const QSize &iconSize)
std::optional< QNapi::Object > makeJsStatusBarMenuItemOptions(QOhosJsState &jsState, const QIcon &icon, const QSize &iconSize)
std::shared_ptr< void > registerOhosRightMenuClickListener(QOhosJsState &jsState, QOhosConsumer< std::string > clickedMenuCodeConsumer)
constexpr QSize defaultStatusBarMenuItemIconSize(48, 48)
QNapi::Object makeJsStatusBarMenuItemWithAction(QOhosJsState &jsState, const std::string &title, const std::string &menuCode, const QIcon &icon, const QSize &iconSize)