Merge pull request from gexgd0419/ui-tab-order

Add helper for setting tab orders automatically
This commit is contained in:
DavidXanatos 2024-10-21 14:59:15 +02:00 committed by GitHub
commit b090993222
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 144 additions and 53 deletions

View File

@ -0,0 +1,124 @@
#include "stdafx.h"
#include "TabOrder.h"
// Items to be sorted by row & col
template <class T>
struct ChildItem
{
T item;
int row, col;
template <class U>
ChildItem(U&& item, int row, int col)
: item(std::forward<U>(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<QWidget*>& widgets);
void GetWidgetsInOrder(QLayout* layout, std::vector<QWidget*>& widgets);
// Fills the given list with widgets in the correct tab order (recursively)
void GetWidgetsInOrder(QWidget* widget, std::vector<QWidget*>& 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<QTabWidget*>(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<QWidget*>& 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<ChildItem<QLayoutItem*>> items;
if (QGridLayout* gridLayout = qobject_cast<QGridLayout*>(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<QFormLayout*>(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<QWidget*> 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<QWidget*> widgets;
GetWidgetsInOrder(root, widgets);
QWidget* prev = nullptr;
for (QWidget* widget : widgets)
{
if (prev)
QWidget::setTabOrder(prev, widget);
prev = widget;
}
}

View File

@ -0,0 +1,4 @@
#pragma once
void SetTabOrder(QWidget* root);
void SetTabOrder(QLayout* root);

View File

@ -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 \

View File

@ -299,6 +299,7 @@
<ClCompile Include="Helpers\ReadDirectoryChanges.cpp" />
<ClCompile Include="Helpers\ReadDirectoryChangesPrivate.cpp" />
<ClCompile Include="Helpers\StorageInfo.cpp" />
<ClCompile Include="Helpers\TabOrder.cpp" />
<ClCompile Include="Helpers\WinAdmin.cpp" />
<ClCompile Include="Helpers\WindowFromPointEx.cpp" />
<ClCompile Include="Helpers\WinHelper.cpp" />
@ -485,6 +486,7 @@
<ClInclude Include="Helpers\ReadDirectoryChanges.h" />
<ClInclude Include="Helpers\ReadDirectoryChangesPrivate.h" />
<ClInclude Include="Helpers\StorageInfo.h" />
<ClInclude Include="Helpers\TabOrder.h" />
<ClInclude Include="Helpers\ThreadSafeQueue.h" />
<ClInclude Include="Helpers\WinAdmin.h" />
<QtMoc Include="Models\MonitorModel.h" />

View File

@ -237,6 +237,9 @@
<ClCompile Include="Windows\ExtractDialog.cpp">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="Helpers\TabOrder.cpp">
<Filter>Helpers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@ -278,6 +281,9 @@
<ClInclude Include="CustomStyles.h">
<Filter>SandMan</Filter>
</ClInclude>
<ClInclude Include="Helpers\TabOrder.h">
<Filter>Helpers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtMoc Include="SandMan.h">

View File

@ -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<QWidget*>();
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<CSbieIni>& 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<CSbieIni>& 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<CSbieIni>& 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<CSbieIni>& pBox, const QStri
this->addAction(pSetTree);
}
m_pSearch->setPlaceholderText(tr("Search for options"));
SetTabOrder(this);
}
void COptionsWindow::ApplyIniEditFont()

View File

@ -17,6 +17,7 @@
#include <qfontdialog.h>
#include <QJsonDocument>
#include <QJsonObject>
#include "Helpers/TabOrder.h"
#include <windows.h>
@ -628,6 +629,8 @@ CSettingsWindow::CSettingsWindow(QWidget* parent)
this->addAction(pSetTree);
}
m_pSearch->setPlaceholderText(tr("Search for settings"));
SetTabOrder(this);
}
void CSettingsWindow::ApplyIniEditFont()