9#include <QtCore/private/qcore_ohos_p.h>
10#include <QtCore/qdatetime.h>
11#include <QtCore/qobject.h>
12#include <QtGui/private/qhighdpiscaling_p.h>
13#include <QtGui/private/qohosimageconversions_p.h>
14#include <QtGui/qguiapplication.h>
15#include <QtGui/qicon.h>
16#include <QtGui/qpa/qplatformmenu.h>
17#include <QtGui/qscreen.h>
20#include <qohosjsscopedataowner.h>
36 return !hoverTips.empty() ? hoverTips :
" ";
41 return [](QOhosJsState &jsState) {
42 return QNapi::Array::New(jsState.env());
48 auto optQAbility = jsState.defaultQAbility();
50 qOhosReportFatalErrorAndAbort(
"%s: no default Ability instance", Q_FUNC_INFO);
52 return optQAbility->eval<QNapi::Object>(
"context");
56 QOhosJsState &jsState,
std::function<
void()> leftClickListener)
58 return registerQOhosOnOffMethodsBasedEventHandler(
59 jsState.eval<QNapi::Object>(
"@kit.StatusBarExtensionKit.statusBarManager"),
61 [leftClickListener = std::move(leftClickListener)](
const QOhosCallbackInfo &cbInfo) {
62 auto eventData = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
63 auto optIconClickType = QNapi::getOptionalPropOrEmpty<QNapi::String>(
64 QNapi::getOptionalPropOrEmpty<QNapi::Object>(eventData,
"data"),
67 if (optIconClickType.IsEmpty()) {
69 "%s: no 'iconClickType' in the event (%s), ignoring it",
70 Q_FUNC_INFO, QNapi::toJsonString(eventData).c_str());
74 if (optIconClickType.Utf8Value() ==
"leftClick")
82 "@kit.StatusBarExtensionKit.statusBarManager.removeFromStatusBar(*)",
83 {getContextForStatusBarManager(jsState)});
85 qOhosPrintfDebug(
"%s: Successfully removed icon from status bar", Q_FUNC_INFO);
91 "@kit.StatusBarExtensionKit.statusBarManager.addToStatusBar(*)",
92 {getContextForStatusBarManager(jsState), statusBarItem});
94 qOhosPrintfDebug(
"%s: Successfully added icon to status bar [Statusbar] ", Q_FUNC_INFO);
96 return QtOhos::makeDestroyNotifier(
98 QOhosJsThreadGateway::runAndWait(&removeIconFromOhosStatusBar, Q_FUNC_INFO);
104 qOhosPrintfDebug(
"%s", Q_FUNC_INFO);
106 if (iconData.IsEmpty()) {
107 qOhosPrintfError(
"%s: Icon data is empty", Q_FUNC_INFO);
112 "@kit.StatusBarExtensionKit.statusBarManager.updateStatusBarIcon(*)",
113 {getContextForStatusBarManager(jsState), iconData});
115 qOhosPrintfDebug(
"%s: Successfully updated status bar icon", Q_FUNC_INFO);
120 return jsState.evalToPromiseOrRejectOnThrow(
121 "@kit.StatusBarExtensionKit.statusBarManager.updateStatusBarHoverTips(*)",
122 {getContextForStatusBarManager(jsState), applyWorkaroundForEmptyHoverTips(hoverTips)});
128 "@kit.StatusBarExtensionKit.statusBarManager.updateStatusBarMenu(*)",
129 {getContextForStatusBarManager(jsState), statusBarGroupMenus});
131 qOhosPrintfDebug(
"%s: Successfully updated status bar menu", Q_FUNC_INFO);
135 QOhosJsState &jsState, QNapi::Object statusBarIcon,
const std::string &title,
136 QNapi::Array statusBarGroupMenus,
std::optional<
std::string> hoverTips)
138 auto *env = jsState.env();
140 auto quickOperation = QNapi::makeObject(
144 {
"height", quickOperationHeight},
148 auto statusBarItem = QNapi::makeObject(
151 {
"icons", statusBarIcon},
152 {
"quickOperation", quickOperation},
153 {
"statusBarGroupMenu", statusBarGroupMenus},
156 if (hoverTips.has_value())
157 statusBarItem.set(
"hoverTips", applyWorkaroundForEmptyHoverTips(hoverTips.value()));
159 return statusBarItem;
163 const QIcon &icon,
const QSize &imageSize,
const QColor &fallbackContentColor)
165 auto iconImage = icon.pixmap(imageSize).toImage();
166 if (!iconImage.isNull())
169 auto fallbackImage = QImage(imageSize, QImage::Format_RGBA8888);
170 fallbackImage.fill(fallbackContentColor);
171 return fallbackImage;
176 const QSize iconSize(48, 48);
177 return makeDisplayDensityScaledJsPixelMapFromQImage(
178 jsState, convertIconToScaledImage(icon, iconSize, Qt::transparent));
183 auto *env = jsState.env();
185 auto trayIcon = makeJsPixelMapFromIcon(jsState, icon);
187 auto imageSize = trayIcon.eval<QNapi::Object>(
"getImageInfoSync().size");
189 int imageWidth = imageSize.get<QNapi::Number>(
"width");
190 int imageHeight = imageSize.get<QNapi::Number>(
"height");
191 qOhosPrintfDebug(
"%s: ceated PixelMap size: %dx%d", Q_FUNC_INFO, imageWidth, imageHeight);
193 return QNapi::makeObject(
202 QOhosJsState &jsState,
const std::string &title,
const std::string &text)
206 return QNapi::makeObject(
209 {
"notificationContentType", jsState.mapOhosEnumToJs(ContentType::NOTIFICATION_CONTENT_BASIC_TEXT)},
223 QOhosJsState &jsState,
const std::string &title,
const std::string &content,
224 const QIcon &icon,
std::optional<
int> optAutoDeletedDelayMs)
226 auto iconPixelMap = makeDisplayDensityScaledJsPixelMapFromQImage(
227 jsState, convertIconToScaledImage(icon, notificationIconSize, Qt::transparent));
228 auto notificationRequest = QNapi::makeObject(
231 {
"content", makeJsNotificationContent(jsState, title, content)},
232 {
"smallIcon", iconPixelMap},
234 if (optAutoDeletedDelayMs.has_value()) {
235 notificationRequest.set(
237 QDateTime::currentMSecsSinceEpoch() + optAutoDeletedDelayMs.value());
240 return notificationRequest;
243class QOhosSystemTrayIcon
final :
public QPlatformSystemTrayIcon
255 const QString &title,
const QString &msg,
const QIcon &icon,
256 MessageIcon iconType,
int msecs)
override;
265 std::optional<QString> m_optToolTip;
266 QPlatformMenu *m_menu =
nullptr;
270 std::shared_ptr<
void> m_statusBarItemHandle;
271 std::shared_ptr<
void> m_iconLeftClickListenerHandle;
279void QOhosSystemTrayIcon::
init()
281 if (m_optJsScopeData)
284 auto jsStatusBarGroupMenusFactory =
286 ?
static_cast<QOhosStatusBarMenu *>(m_menu)->makeJsStatusBarGroupMenusFactory()
287 : makeEmptyJsArrayFactory();
289 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
290 m_optJsScopeData.emplace();
291 QOhosJsThreadGateway::runAndWait(
292 [&](QOhosJsState &jsState) {
293 auto jsStatusBarIcon = makeJsStatusBarIcon(jsState, m_icon);
294 auto jsStatusBarGroupMenus = jsStatusBarGroupMenusFactory(jsState);
295 auto optHoverTipsString = qTransform(
297 [](
const auto &toolTip) {
298 return toolTip.toStdString();
300 auto jsStatusBarItem = makeJsStatusBarItem(
301 jsState, jsStatusBarIcon, ohosSystemTrayItemTitle, jsStatusBarGroupMenus, optHoverTipsString);
302 **m_optJsScopeData = JsScopeData {
303 .m_statusBarItemHandle = addItemToOhosStatusBar(jsState, jsStatusBarItem),
304 .m_iconLeftClickListenerHandle = registerOhosIconLeftClickListener(
307 selfRef.visitInQtThreadIfAlive(
309 Q_EMIT self.activated(QPlatformSystemTrayIcon::Trigger);
316 qOhosPrintfDebug(
"%s: System tray icon initialized", Q_FUNC_INFO);
321 m_optJsScopeData.reset();
326 if (!m_optJsScopeData)
331 QOhosJsThreadGateway::runAndWait(
332 [&](QOhosJsState &jsState) {
333 updateOhosStatusBarIcon(jsState, makeJsStatusBarIcon(jsState, icon));
340 m_optToolTip = tooltip;
342 if (m_optJsScopeData) {
343 QOhosJsThreadGateway::invokeAndWaitForContinue(
344 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
345 updateOhosStatusBarHoverTips(jsState, tooltip.toStdString())
346 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"updateStatusBarHoverTips()"))
347 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
355 return trayIconGeometry;
359 const QString &title,
const QString &msg,
const QIcon &icon, MessageIcon iconType,
int msecs)
362 QOhosJsThreadGateway::invokeAndWaitForContinue(
363 [&](QOhosJsState &jsState, QOhosTaskPromise<> taskPromise) {
364 auto notificationRequest = makeJsNotificationRequest(
365 jsState, title.toStdString(), msg.toStdString(), icon,
366 msecs > 0 ? std::optional(msecs) : std::nullopt);
367 jsState.evalToPromiseOrRejectOnThrow(
"@ohos.notificationManager.publish(*)", {notificationRequest})
368 .onCatch(QtOhos::makeErrorLoggingJsCallback(
"publish()"))
369 .onFinally(std::move(taskPromise).makeChained(Q_FUNC_INFO));
386 if (m_menu ==
nullptr)
387 return makeQOhosStatusBarMenu().release();
393 qOhosPrintfDebug(
"%s: Updating status bar menu", Q_FUNC_INFO);
397 if (!m_optJsScopeData) {
398 qOhosPrintfDebug(
"%s: System tray not initialized yet", Q_FUNC_INFO);
402 auto jsStatusBarGroupMenusFactory =
404 ?
static_cast<QOhosStatusBarMenu *>(m_menu)->makeJsStatusBarGroupMenusFactory()
405 : makeEmptyJsArrayFactory();
407 QOhosJsThreadGateway::runAndWait(
408 [&](QOhosJsState &jsState) {
409 updateOhosStatusBarMenu(jsState, jsStatusBarGroupMenusFactory(jsState));
418 return std::make_unique<QOhosSystemTrayIcon>();
void init() override
This method is called to initialize the platform dependent implementation.
void cleanup() override
This method is called to cleanup the platform dependent implementation.
void showMessage(const QString &title, const QString &msg, const QIcon &icon, MessageIcon iconType, int msecs) override
Shows a balloon message for the entry with the given title, message msg and icon for the time specifi...
void updateMenu(QPlatformMenu *menu) override
This method is called when the system tray menu did change.
QPlatformMenu * createMenu() const override
This method allows platforms to use a different QPlatformMenu for system tray menus than what would n...
QRect geometry() const override
This method returns the geometry of the platform dependent system tray icon on the screen.
bool supportsMessages() const override
Returns true if the system tray supports messages on the platform.
bool isSystemTrayAvailable() const override
Returns true if the system tray is available on the platform.
void updateToolTip(const QString &tooltip) override
This method is called when the tooltip text did change.
void updateIcon(const QIcon &icon) override
This method is called when the icon did change.
Combined button and popup list for selecting options.
QNapi::Promise updateOhosStatusBarHoverTips(QOhosJsState &jsState, const std::string &hoverTips)
std::function< QNapi::Array(QOhosJsState &)> makeEmptyJsArrayFactory()
QNapi::Object makeJsStatusBarItem(QOhosJsState &jsState, QNapi::Object statusBarIcon, const std::string &title, QNapi::Array statusBarGroupMenus, std::optional< std::string > hoverTips)
const auto notificationIconSize
void updateOhosStatusBarMenu(QOhosJsState &jsState, QNapi::Array statusBarGroupMenus)
std::shared_ptr< void > registerOhosIconLeftClickListener(QOhosJsState &jsState, std::function< void()> leftClickListener)
QImage convertIconToScaledImage(const QIcon &icon, const QSize &imageSize, const QColor &fallbackContentColor)
QNapi::Object makeJsStatusBarIcon(QOhosJsState &jsState, const QIcon &icon)
QNapi::Object makeJsPixelMapFromIcon(QOhosJsState &jsState, const QIcon &icon)
void updateOhosStatusBarIcon(QOhosJsState &jsState, QNapi::Object iconData)
std::shared_ptr< void > addItemToOhosStatusBar(QOhosJsState &jsState, QNapi::Object statusBarItem)
std::string applyWorkaroundForEmptyHoverTips(const std::string &hoverTips)
QNapi::Object makeJsNotificationRequest(QOhosJsState &jsState, const std::string &title, const std::string &content, const QIcon &icon, std::optional< int > optAutoDeletedDelayMs)
QNapi::Object getContextForStatusBarManager(QOhosJsState &jsState)
const auto trayIconGeometry
constexpr int quickOperationHeight
void removeIconFromOhosStatusBar(QOhosJsState &jsState)
const std::string ohosSystemTrayItemTitle
QNapi::Object makeJsNotificationContent(QOhosJsState &jsState, const std::string &title, const std::string &text)
QT_BEGIN_NAMESPACE std::unique_ptr< QPlatformSystemTrayIcon > makeQOhosSystemTrayIcon()