From 2266702a0b2fa327e7b371470cb68934f13ddc1e Mon Sep 17 00:00:00 2001 From: Cyril Anisimov Date: Wed, 18 Dec 2024 23:45:43 +0100 Subject: [PATCH] add `focusControl` with utility functions for focus control --- client/CMakeLists.txt | 2 + client/utils/focusControl.cpp | 131 ++++++++++++++++++++++++++++++++++ client/utils/focusControl.h | 30 ++++++++ 3 files changed, 163 insertions(+) create mode 100644 client/utils/focusControl.cpp create mode 100644 client/utils/focusControl.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 05f9f17c..beebc3ee 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -146,6 +146,7 @@ set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h ${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h ${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h + ${CMAKE_CURRENT_LIST_DIR}/utils/focusControl.h ) # Mozilla headres @@ -197,6 +198,7 @@ set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp ${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp + ${CMAKE_CURRENT_LIST_DIR}/utils/focusControl.cpp ) # Mozilla sources diff --git a/client/utils/focusControl.cpp b/client/utils/focusControl.cpp new file mode 100644 index 00000000..a3107d55 --- /dev/null +++ b/client/utils/focusControl.cpp @@ -0,0 +1,131 @@ +#include "focusControl.h" +#include "utils/focusControl.h" + +#include +#include +#include + +namespace focusControl +{ + QPointF getItemCenterPointOnScene(QQuickItem *item) + { + const auto x0 = item->x() + (item->width() / 2); + const auto y0 = item->y() + (item->height() / 2); + return item->parentItem()->mapToScene(QPointF { x0, y0 }); + } + + bool isEnabled(QObject *obj) + { + const auto item = qobject_cast(obj); + return item && item->isEnabled(); + } + + bool isVisible(QObject *item) + { + const auto res = item->property("visible").toBool(); + return res; + } + + bool isFocusable(QObject *item) + { + const auto res = item->property("isFocusable").toBool(); + return res; + } + + bool isListView(QObject *item) + { + return item->inherits("QQuickListView"); + } + + bool isOnTheScene(QObject *object) + { + QQuickItem *item = qobject_cast(object); + if (!item) { + qWarning() << "Couldn't recognize object as item"; + return false; + } + + if (!item->isVisible()) { + return false; + } + + QRectF itemRect = item->mapRectToScene(item->childrenRect()); + + QQuickWindow *window = item->window(); + if (!window) { + qWarning() << "Couldn't get the window on the Scene check"; + return false; + } + + const auto contentItem = window->contentItem(); + if (!contentItem) { + qWarning() << "Couldn't get the content item on the Scene check"; + return false; + } + QRectF windowRect = contentItem->childrenRect(); + const auto res = (windowRect.contains(itemRect) || isListView(item)); + return res; + } + + bool isMore(QObject *item1, QObject *item2) + { + return !isLess(item1, item2); + } + + bool isLess(QObject *item1, QObject *item2) + { + const auto p1 = getItemCenterPointOnScene(qobject_cast(item1)); + const auto p2 = getItemCenterPointOnScene(qobject_cast(item2)); + return (p1.y() == p2.y()) ? (p1.x() < p2.x()) : (p1.y() < p2.y()); + } + + QList getSubChain(QObject *object) + { + QList res; + if (!object) { + qDebug() << "The object is NULL"; + return res; + } + + const auto children = object->children(); + + for (const auto child : children) { + if (child && isFocusable(child) && isOnTheScene(child) && isEnabled(child)) { + res.append(child); + } else { + res.append(getSubChain(child)); + } + } + return res; + } + + QList getItemsChain(QObject *object) + { + QList res; + if (!object) { + qDebug() << "The object is NULL"; + return res; + } + + const auto children = object->children(); + + for (const auto child : children) { + if (child && isFocusable(child) && isEnabled(child) && isVisible(child)) { + res.append(child); + } else { + res.append(getItemsChain(child)); + } + } + return res; + } + + void printItems(const QList &items, QObject *current_item) + { + for (const auto &item : items) { + QQuickItem *i = qobject_cast(item); + QPointF coords { getItemCenterPointOnScene(i) }; + QString prefix = current_item == i ? "==>" : " "; + qDebug() << prefix << " Item: " << i << " with coords: " << coords; + } + } +} // namespace focusControl \ No newline at end of file diff --git a/client/utils/focusControl.h b/client/utils/focusControl.h new file mode 100644 index 00000000..96ab3a83 --- /dev/null +++ b/client/utils/focusControl.h @@ -0,0 +1,30 @@ +#ifndef FOCUSCONTROL_H +#define FOCUSCONTROL_H + +#include +#include + +namespace focusControl +{ + bool isEnabled(QObject *item); + bool isVisible(QObject *item); + bool isFocusable(QObject *item); + bool isListView(QObject *item); + bool isOnTheScene(QObject *object); + bool isMore(QObject *item1, QObject *item2); + bool isLess(QObject *item1, QObject *item2); + + /*! + * \brief Make focus chain of elements which are on the scene + */ + QList getSubChain(QObject *object); + + /*! + * \brief Make focus chain of elements which could be not on the scene + */ + QList getItemsChain(QObject *object); + + void printItems(const QList &items, QObject *current_item); +} + +#endif // FOCUSCONTROL_H \ No newline at end of file