diff --git a/client/ui/controllers/focusController.cpp b/client/ui/controllers/focusController.cpp index 27be7d2a..e70391a8 100644 --- a/client/ui/controllers/focusController.cpp +++ b/client/ui/controllers/focusController.cpp @@ -6,6 +6,67 @@ #include +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()) { + // qDebug() << "===>> The item is not visible: " << item; + 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)); + // qDebug() << (res ? "===>> item is inside the Scene" : "===>> ITEM IS OUTSIDE THE SCENE") << " itemRect: " << itemRect << "; windowRect: " << windowRect; + return res; +} + +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; +} + FocusController::FocusController(QQmlApplicationEngine* engine, QObject *parent) : QObject{parent} , m_engine{engine} @@ -25,16 +86,16 @@ FocusController::FocusController(QQmlApplicationEngine* engine, QObject *parent) }); } -void FocusController::nextItem(bool isForwardOrder) +void FocusController::nextItem(Direction direction) { if (m_lvfc) { - isForwardOrder ? focusNextListViewItem() : focusPreviousListViewItem(); + direction == Direction::Forward ? focusNextListViewItem() : focusPreviousListViewItem(); qDebug() << "===>> [handling the ListView]"; return; } - reload(isForwardOrder); + reload(direction); if(m_focusChain.empty()) { qWarning() << "There are no items to navigate"; @@ -60,13 +121,13 @@ void FocusController::nextItem(bool isForwardOrder) if(isListView(m_focusedItem)) { qDebug() << "===>> [Found ListView]"; m_lvfc = new ListViewFocusController(m_focusedItem, this); - if(isForwardOrder) { + if(direction == Direction::Forward) { m_lvfc->viewToBegin(); - m_lvfc->nextElement(); + m_lvfc->nextDelegate(); focusNextListViewItem(); } else { m_lvfc->viewToEnd(); - m_lvfc->previousElement(); + m_lvfc->previousDelegate(); focusPreviousListViewItem(); } return; @@ -90,62 +151,67 @@ void FocusController::nextItem(bool isForwardOrder) void FocusController::focusNextListViewItem() { - m_lvfc->focusNextItem(); - if (m_lvfc->isLastFocusItemInListView() || m_lvfc->isReturnNeeded()) { - qDebug() << "===>> [Last item in ListView was reached]"; + qDebug() << "===>> [Last item in ListView was reached. Going to the NEXT element after ListView]"; delete m_lvfc; m_lvfc = nullptr; + nextItem(Direction::Forward); + return; } else if (m_lvfc->isLastFocusItemInDelegate()) { qDebug() << "===>> [End of delegate elements was reached. Going to the next delegate]"; m_lvfc->resetFocusChain(); - m_lvfc->nextElement(); + m_lvfc->nextDelegate(); m_lvfc->viewAtCurrentIndex(); } + + m_lvfc->focusNextItem(); } void FocusController::focusPreviousListViewItem() { - m_lvfc->focusPreviousItem(); - if (m_lvfc->isFirstFocusItemInListView() || m_lvfc->isReturnNeeded()) { + qDebug() << "===>> [First item in ListView was reached. Going to the PREVIOUS element after ListView]"; delete m_lvfc; m_lvfc = nullptr; + nextItem(Direction::Backward); + return; } else if (m_lvfc->isFirstFocusItemInDelegate()) { m_lvfc->resetFocusChain(); - m_lvfc->decrementIndex(); + m_lvfc->previousDelegate(); m_lvfc->viewAtCurrentIndex(); } + + m_lvfc->focusPreviousItem(); } void FocusController::nextKeyTabItem() { - nextItem(true); + nextItem(Direction::Forward); } void FocusController::previousKeyTabItem() { - nextItem(false); + nextItem(Direction::Backward); } void FocusController::nextKeyUpItem() { - nextItem(false); + nextItem(Direction::Backward); } void FocusController::nextKeyDownItem() { - nextItem(true); + nextItem(Direction::Forward); } void FocusController::nextKeyLeftItem() { - nextItem(false); + nextItem(Direction::Backward); } void FocusController::nextKeyRightItem() { - nextItem(true); + nextItem(Direction::Forward); } void FocusController::setFocusOnDefaultItem() @@ -154,7 +220,7 @@ void FocusController::setFocusOnDefaultItem() m_defaultFocusItem->forceActiveFocus(); } -void FocusController::reload(bool isForwardOrder) +void FocusController::reload(Direction direction) { m_focusChain.clear(); @@ -174,7 +240,7 @@ void FocusController::reload(bool isForwardOrder) m_focusChain.append(getSubChain(rootObject)); - std::sort(m_focusChain.begin(), m_focusChain.end(), isForwardOrder? isLess : isMore); + std::sort(m_focusChain.begin(), m_focusChain.end(), direction == Direction::Forward ? isLess : isMore); if (m_focusChain.empty()) { qWarning() << "Focus chain is empty!"; diff --git a/client/ui/controllers/focusController.h b/client/ui/controllers/focusController.h index e6368e98..a4851032 100644 --- a/client/ui/controllers/focusController.h +++ b/client/ui/controllers/focusController.h @@ -35,10 +35,15 @@ public: Q_INVOKABLE void dropRootObject(QObject* object); private: - void nextItem(bool isForwardOrder); + enum class Direction { + Forward, + Backward, + }; + + void nextItem(Direction direction); void focusNextListViewItem(); void focusPreviousListViewItem(); - void reload(bool isForwardOrder); + void reload(Direction direction); QSharedPointer m_engine; // Pointer to engine to get root object QList m_focusChain; // List of current objects to be focused diff --git a/client/ui/controllers/listViewFocusController.cpp b/client/ui/controllers/listViewFocusController.cpp index a4b13fb4..b899dfe6 100644 --- a/client/ui/controllers/listViewFocusController.cpp +++ b/client/ui/controllers/listViewFocusController.cpp @@ -10,7 +10,6 @@ bool isVisible(QObject* item) { const auto res = item->property("visible").toBool(); - // qDebug() << "==>> " << (res ? "VISIBLE" : "NOT visible") << item; return res; } @@ -39,50 +38,13 @@ bool isMore(QObject* item1, QObject* item2) return !isLess(item1, item2); } -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()) { - // qDebug() << "===>> The item is not visible: " << item; - 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)); - // qDebug() << (res ? "===>> item is inside the Scene" : "===>> ITEM IS OUTSIDE THE SCENE") << " itemRect: " << itemRect << "; windowRect: " << windowRect; - return res; -} - bool isEnabled(QObject* obj) { const auto item = qobject_cast(obj); return item && item->isEnabled(); } -QList getSubChain(QObject* object) +QList getItemsChain(QObject* object) { QList res; if (!object) { @@ -95,12 +57,12 @@ QList getSubChain(QObject* object) for(const auto child : children) { if (child && isFocusable(child) - && isOnTheScene(child) && isEnabled(child) + && isVisible(child) ) { res.append(child); } else { - res.append(getSubChain(child)); + res.append(getItemsChain(child)); } } return res; @@ -175,13 +137,13 @@ int ListViewFocusController::currentIndex() const return m_delegateIndex; } -void ListViewFocusController::nextElement() +void ListViewFocusController::nextDelegate() { - qDebug() << "===>> Current section: " << m_currentSectionString.at(static_cast(m_currentSection)); switch(m_currentSection) { case Section::Default: { if(m_header) { m_currentSection = Section::Header; + viewToBegin(); break; } } @@ -197,6 +159,7 @@ void ListViewFocusController::nextElement() break; } else if (m_footer) { m_currentSection = Section::Footer; + viewToEnd(); break; } case Section::Footer: { @@ -209,10 +172,9 @@ void ListViewFocusController::nextElement() break; } } - } -void ListViewFocusController::previousElement() +void ListViewFocusController::previousDelegate() { switch(m_currentSection) { case Section::Default: { @@ -224,7 +186,6 @@ void ListViewFocusController::previousElement() case Section::Footer: { if (size() > 0) { m_currentSection = Section::Delegate; - m_focusedItemIndex = size() - 1; // workarount to default value == -1 break; } } @@ -298,16 +259,17 @@ QQuickItem* ListViewFocusController::focusedItem() void ListViewFocusController::focusNextItem() { if (m_isReturnNeeded) { + qDebug() << "===>> RETURN IS NEEDED..."; return; } if (m_focusChain.empty()) { qDebug() << "Empty focusChain with current delegate: " << currentDelegate() << "Scanning for elements..."; - m_focusChain = getSubChain(currentDelegate()); + m_focusChain = getItemsChain(currentDelegate()); } if (m_focusChain.empty()) { - qWarning() << "No elements found. Returning from ListView..."; - nextElement(); + qWarning() << "No elements found in the delegate. Going to next delegate..."; + nextDelegate(); focusNextItem(); return; } @@ -325,14 +287,17 @@ void ListViewFocusController::focusPreviousItem() if (m_focusChain.empty()) { qDebug() << "Empty focusChain with current delegate: " << currentDelegate() << "Scanning for elements..."; - m_focusChain = getSubChain(currentDelegate()); + m_focusChain = getItemsChain(currentDelegate()); } if (m_focusChain.empty()) { - qWarning() << "No elements found. Returning from ListView..."; - previousElement(); + qWarning() << "No elements found in the delegate. Going to next delegate..."; + previousDelegate(); focusPreviousItem(); return; } + if (m_focusedItemIndex == -1) { + m_focusedItemIndex = m_focusChain.size(); + } m_focusedItemIndex--; m_focusedItem = qobject_cast(m_focusChain.at(m_focusedItemIndex)); qDebug() << "==>> Focused Item: " << m_focusedItem << " with Index: " << m_focusedItemIndex; diff --git a/client/ui/controllers/listViewFocusController.h b/client/ui/controllers/listViewFocusController.h index e7d83bbf..66c31228 100644 --- a/client/ui/controllers/listViewFocusController.h +++ b/client/ui/controllers/listViewFocusController.h @@ -7,7 +7,8 @@ #include -bool isListView(QObject* item); +bool isEnabled(QObject* item); +bool isFocusable(QObject* item); bool isMore(QObject* item1, QObject* item2); bool isLess(QObject* item1, QObject* item2); QList getSubChain(QObject* object); @@ -29,8 +30,8 @@ public: explicit ListViewFocusController(QQuickItem* listView, QObject* parent = nullptr); ~ListViewFocusController(); - void nextElement(); - void previousElement(); + void nextDelegate(); + void previousDelegate(); void decrementIndex(); void focusNextItem(); void focusPreviousItem(); diff --git a/client/ui/qml/main2.qml b/client/ui/qml/main2.qml index 83a6667f..f1a87ba9 100644 --- a/client/ui/qml/main2.qml +++ b/client/ui/qml/main2.qml @@ -15,6 +15,7 @@ import "Pages2" Window { id: root objectName: "mainWindow" + visible: true width: GC.screenWidth height: GC.screenHeight @@ -32,7 +33,7 @@ Window { title: "AmneziaVPN" - Item { + Item { // This item is needed for focus handling id: defaultFocusItem objectName: "defaultFocusItem" @@ -210,8 +211,6 @@ Window { clickedFunc: function() { hidePassword = !hidePassword } - - // KeyNavigation.tab: saveButton } BasicButtonType {