diff --git a/SandboxiePlus/SandMan/Helpers/TabOrder.cpp b/SandboxiePlus/SandMan/Helpers/TabOrder.cpp new file mode 100644 index 00000000..0009ddd3 --- /dev/null +++ b/SandboxiePlus/SandMan/Helpers/TabOrder.cpp @@ -0,0 +1,124 @@ +#include "stdafx.h" +#include "TabOrder.h" + +// Items to be sorted by row & col +template +struct ChildItem +{ + T item; + int row, col; + template + ChildItem(U&& item, int row, int col) + : item(std::forward(item)), row(row), col(col) {} + bool operator<(const ChildItem& other) const // make it sortable + { + if (row != other.row) + return row < other.row; + return col < other.col; // sort first by row, then by col + } +}; + +void GetWidgetsInOrder(QWidget* widget, std::vector& widgets); +void GetWidgetsInOrder(QLayout* layout, std::vector& widgets); + +// Fills the given list with widgets in the correct tab order (recursively) +void GetWidgetsInOrder(QWidget* widget, std::vector& widgets) +{ + if (widget->focusPolicy() != Qt::FocusPolicy::NoFocus) + { + widgets.push_back(widget); // add the widget itself + } + + if (QLayout* layout = widget->layout()) + { + // if managed by a layout + GetWidgetsInOrder(layout, widgets); + return; + } + + // If not managed by a layout, try to get its child widgets. + // Here only children of QTabWidgets are actually processed. + // More branches will be necessary if there's another type of container widget used. + + if (auto* parent = qobject_cast(widget)) + { + int cnt = parent->count(); + for (int i = 0; i < cnt; i++) + GetWidgetsInOrder(parent->widget(i), widgets); + } +} + +// Fills the given list with widgets in the correct tab order (recursively) +void GetWidgetsInOrder(QLayout* layout, std::vector& widgets) +{ + // Get a list of layout items in the layout, + // then sort by rows and columns to get the correct tab order + + int cnt = layout->count(); + std::vector> items; + + if (QGridLayout* gridLayout = qobject_cast(layout)) + { + for (int i = 0; i < cnt; i++) + { + int row, col, rowSpan, colSpan; + gridLayout->getItemPosition(i, &row, &col, &rowSpan, &colSpan); + items.emplace_back(gridLayout->itemAt(i), row, col); + } + } + else if (QFormLayout* formLayout = qobject_cast(layout)) + { + for (int i = 0; i < cnt; i++) + { + int row; + QFormLayout::ItemRole role; + formLayout->getItemPosition(i, &row, &role); + items.emplace_back(formLayout->itemAt(i), row, (int)role); + } + } + else + { + // For other types of layouts, preserve the order in the layout + for (int i = 0; i < cnt; i++) + { + items.emplace_back(layout->itemAt(i), 0, i); + } + } + + std::stable_sort(items.begin(), items.end()); + + // process all child layouts/widgets in the sorted order + for (const auto& item : items) + { + if (QLayout* l = item.item->layout()) + GetWidgetsInOrder(l, widgets); + else if (QWidget* w = item.item->widget()) + GetWidgetsInOrder(w, widgets); + } +} + +void SetTabOrder(QWidget* root) +{ + std::vector widgets; + GetWidgetsInOrder(root, widgets); + QWidget* prev = nullptr; + for (QWidget* widget : widgets) + { + if (prev) + QWidget::setTabOrder(prev, widget); + prev = widget; + } +} + +void SetTabOrder(QLayout* root) +{ + std::vector widgets; + GetWidgetsInOrder(root, widgets); + QWidget* prev = nullptr; + for (QWidget* widget : widgets) + { + if (prev) + QWidget::setTabOrder(prev, widget); + prev = widget; + } +} diff --git a/SandboxiePlus/SandMan/Helpers/TabOrder.h b/SandboxiePlus/SandMan/Helpers/TabOrder.h new file mode 100644 index 00000000..d4f49f9b --- /dev/null +++ b/SandboxiePlus/SandMan/Helpers/TabOrder.h @@ -0,0 +1,4 @@ +#pragma once + +void SetTabOrder(QWidget* root); +void SetTabOrder(QLayout* root); diff --git a/SandboxiePlus/SandMan/SandMan.pri b/SandboxiePlus/SandMan/SandMan.pri index 5ff41db1..b6cede3c 100644 --- a/SandboxiePlus/SandMan/SandMan.pri +++ b/SandboxiePlus/SandMan/SandMan.pri @@ -23,6 +23,7 @@ HEADERS += ./stdafx.h \ ./Helpers/StorageInfo.h \ ./Helpers/ReadDirectoryChanges.h \ ./Helpers/ReadDirectoryChangesPrivate.h \ + ./Helpers/TabOrder.h \ ./Windows/RecoveryWindow.h \ ./Windows/PopUpWindow.h \ ./Windows/SnapshotsWindow.h \ @@ -74,6 +75,7 @@ SOURCES += ./main.cpp \ ./Helpers/ReadDirectoryChanges.cpp \ ./Helpers/ReadDirectoryChangesPrivate.cpp \ ./Helpers/WindowFromPointEx.cpp \ + ./Helpers/TabOrder.cpp \ ./Windows/OptionsWindow.cpp \ ./Windows/PopUpWindow.cpp \ ./Windows/RecoveryWindow.cpp \ diff --git a/SandboxiePlus/SandMan/SandMan.vcxproj b/SandboxiePlus/SandMan/SandMan.vcxproj index bb436e28..bd8db6c4 100644 --- a/SandboxiePlus/SandMan/SandMan.vcxproj +++ b/SandboxiePlus/SandMan/SandMan.vcxproj @@ -299,6 +299,7 @@ + @@ -485,6 +486,7 @@ + diff --git a/SandboxiePlus/SandMan/SandMan.vcxproj.filters b/SandboxiePlus/SandMan/SandMan.vcxproj.filters index c2a47302..23fc3005 100644 --- a/SandboxiePlus/SandMan/SandMan.vcxproj.filters +++ b/SandboxiePlus/SandMan/SandMan.vcxproj.filters @@ -237,6 +237,9 @@ Windows + + Helpers + @@ -278,6 +281,9 @@ SandMan + + Helpers + diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp index d97f80c1..78c117eb 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp @@ -8,55 +8,7 @@ #include "../MiscHelpers/Common/SettingsWidgets.h" #include "Helpers/WinAdmin.h" #include "../Wizards/TemplateWizard.h" - - -static bool IsAncestorOf(QObject* container, QObject* obj) -{ - while (obj) - { - if (obj == container) - return true; - obj = obj->parent(); - } - return false; -} - -static QWidgetList GetTabOrder(QObject* container) -{ - QWidgetList list; - QWidget* pWidget = container->findChild(); - - if (!pWidget) - return list; - list.append(pWidget); - - for (QWidget* pPrev = pWidget->previousInFocusChain(); - pPrev && IsAncestorOf(container, pPrev); - pPrev = pPrev->previousInFocusChain()) - { - list.prepend(pPrev); - } - - for (QWidget* pNext = pWidget->nextInFocusChain(); - pNext && IsAncestorOf(container, pNext); - pNext = pNext->nextInFocusChain()) - { - list.append(pNext); - } - - return list; -} - -static void RestoreTabOrder(const QWidgetList& list) -{ - QWidget* pPrev = nullptr; - for (QWidget* pWidget : list) - { - if (pPrev) - QWidget::setTabOrder(pPrev, pWidget); - pPrev = pWidget; - } -} +#include "Helpers/TabOrder.h" class NoEditDelegate : public QStyledItemDelegate { @@ -324,14 +276,12 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri pDummy->setVisible(false); // merge recovery tabs - QWidgetList tabOrder = GetTabOrder(ui.tabsRecovery); QWidget* pWidget3 = new QWidget(); pWidget3->setLayout(ui.gridLayout_10); ui.gridLayout_24->addWidget(pWidget3, 1, 0); QWidget* pWidget4 = new QWidget(); pWidget4->setLayout(ui.gridLayout_56); ui.gridLayout_24->addWidget(pWidget4, 2, 0); - RestoreTabOrder(tabOrder); delete ui.tabsRecovery; ui.gridLayout_24->setContentsMargins(0, 0, 0, 0); @@ -357,7 +307,6 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri if (iOptionLayout == 1) { // merge stop tabs - tabOrder = GetTabOrder(ui.tabsStop); QWidget* pWidget1 = new QWidget(); pWidget1->setLayout(ui.gridLayout_57); ui.gridLayout_17->addWidget(pWidget1, 1, 0); @@ -371,7 +320,6 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri ui.lblStopOpt->setVisible(false); ui.lblStopOpt->setProperty("hidden", true); ui.gridLayout_17->addWidget(pWidget3, 3, 0); - RestoreTabOrder(tabOrder); delete ui.tabsStop; ui.gridLayout_17->setContentsMargins(0, 0, 0, 0); @@ -718,6 +666,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri this->addAction(pSetTree); } m_pSearch->setPlaceholderText(tr("Search for options")); + + SetTabOrder(this); } void COptionsWindow::ApplyIniEditFont() diff --git a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp index e0bfa296..3d0e1f02 100644 --- a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "Helpers/TabOrder.h" #include @@ -628,6 +629,8 @@ CSettingsWindow::CSettingsWindow(QWidget* parent) this->addAction(pSetTree); } m_pSearch->setPlaceholderText(tr("Search for settings")); + + SetTabOrder(this); } void CSettingsWindow::ApplyIniEditFont()