Merge pull request #4310 from gexgd0419/ui-tab-order
Add helper for setting tab orders automatically
This commit is contained in:
commit
b090993222
SandboxiePlus/SandMan
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void SetTabOrder(QWidget* root);
|
||||
void SetTabOrder(QLayout* root);
|
|
@ -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 \
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue