Merge pull request #4310 from gexgd0419/ui-tab-order
Add helper for setting tab orders automatically
This commit is contained in:
commit
b090993222
|
@ -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/StorageInfo.h \
|
||||||
./Helpers/ReadDirectoryChanges.h \
|
./Helpers/ReadDirectoryChanges.h \
|
||||||
./Helpers/ReadDirectoryChangesPrivate.h \
|
./Helpers/ReadDirectoryChangesPrivate.h \
|
||||||
|
./Helpers/TabOrder.h \
|
||||||
./Windows/RecoveryWindow.h \
|
./Windows/RecoveryWindow.h \
|
||||||
./Windows/PopUpWindow.h \
|
./Windows/PopUpWindow.h \
|
||||||
./Windows/SnapshotsWindow.h \
|
./Windows/SnapshotsWindow.h \
|
||||||
|
@ -74,6 +75,7 @@ SOURCES += ./main.cpp \
|
||||||
./Helpers/ReadDirectoryChanges.cpp \
|
./Helpers/ReadDirectoryChanges.cpp \
|
||||||
./Helpers/ReadDirectoryChangesPrivate.cpp \
|
./Helpers/ReadDirectoryChangesPrivate.cpp \
|
||||||
./Helpers/WindowFromPointEx.cpp \
|
./Helpers/WindowFromPointEx.cpp \
|
||||||
|
./Helpers/TabOrder.cpp \
|
||||||
./Windows/OptionsWindow.cpp \
|
./Windows/OptionsWindow.cpp \
|
||||||
./Windows/PopUpWindow.cpp \
|
./Windows/PopUpWindow.cpp \
|
||||||
./Windows/RecoveryWindow.cpp \
|
./Windows/RecoveryWindow.cpp \
|
||||||
|
|
|
@ -299,6 +299,7 @@
|
||||||
<ClCompile Include="Helpers\ReadDirectoryChanges.cpp" />
|
<ClCompile Include="Helpers\ReadDirectoryChanges.cpp" />
|
||||||
<ClCompile Include="Helpers\ReadDirectoryChangesPrivate.cpp" />
|
<ClCompile Include="Helpers\ReadDirectoryChangesPrivate.cpp" />
|
||||||
<ClCompile Include="Helpers\StorageInfo.cpp" />
|
<ClCompile Include="Helpers\StorageInfo.cpp" />
|
||||||
|
<ClCompile Include="Helpers\TabOrder.cpp" />
|
||||||
<ClCompile Include="Helpers\WinAdmin.cpp" />
|
<ClCompile Include="Helpers\WinAdmin.cpp" />
|
||||||
<ClCompile Include="Helpers\WindowFromPointEx.cpp" />
|
<ClCompile Include="Helpers\WindowFromPointEx.cpp" />
|
||||||
<ClCompile Include="Helpers\WinHelper.cpp" />
|
<ClCompile Include="Helpers\WinHelper.cpp" />
|
||||||
|
@ -485,6 +486,7 @@
|
||||||
<ClInclude Include="Helpers\ReadDirectoryChanges.h" />
|
<ClInclude Include="Helpers\ReadDirectoryChanges.h" />
|
||||||
<ClInclude Include="Helpers\ReadDirectoryChangesPrivate.h" />
|
<ClInclude Include="Helpers\ReadDirectoryChangesPrivate.h" />
|
||||||
<ClInclude Include="Helpers\StorageInfo.h" />
|
<ClInclude Include="Helpers\StorageInfo.h" />
|
||||||
|
<ClInclude Include="Helpers\TabOrder.h" />
|
||||||
<ClInclude Include="Helpers\ThreadSafeQueue.h" />
|
<ClInclude Include="Helpers\ThreadSafeQueue.h" />
|
||||||
<ClInclude Include="Helpers\WinAdmin.h" />
|
<ClInclude Include="Helpers\WinAdmin.h" />
|
||||||
<QtMoc Include="Models\MonitorModel.h" />
|
<QtMoc Include="Models\MonitorModel.h" />
|
||||||
|
|
|
@ -237,6 +237,9 @@
|
||||||
<ClCompile Include="Windows\ExtractDialog.cpp">
|
<ClCompile Include="Windows\ExtractDialog.cpp">
|
||||||
<Filter>Windows</Filter>
|
<Filter>Windows</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Helpers\TabOrder.cpp">
|
||||||
|
<Filter>Helpers</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="stdafx.h">
|
<ClInclude Include="stdafx.h">
|
||||||
|
@ -278,6 +281,9 @@
|
||||||
<ClInclude Include="CustomStyles.h">
|
<ClInclude Include="CustomStyles.h">
|
||||||
<Filter>SandMan</Filter>
|
<Filter>SandMan</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Helpers\TabOrder.h">
|
||||||
|
<Filter>Helpers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="SandMan.h">
|
<QtMoc Include="SandMan.h">
|
||||||
|
|
|
@ -8,55 +8,7 @@
|
||||||
#include "../MiscHelpers/Common/SettingsWidgets.h"
|
#include "../MiscHelpers/Common/SettingsWidgets.h"
|
||||||
#include "Helpers/WinAdmin.h"
|
#include "Helpers/WinAdmin.h"
|
||||||
#include "../Wizards/TemplateWizard.h"
|
#include "../Wizards/TemplateWizard.h"
|
||||||
|
#include "Helpers/TabOrder.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class NoEditDelegate : public QStyledItemDelegate {
|
class NoEditDelegate : public QStyledItemDelegate {
|
||||||
|
@ -324,14 +276,12 @@ COptionsWindow::COptionsWindow(const QSharedPointer<CSbieIni>& pBox, const QStri
|
||||||
pDummy->setVisible(false);
|
pDummy->setVisible(false);
|
||||||
|
|
||||||
// merge recovery tabs
|
// merge recovery tabs
|
||||||
QWidgetList tabOrder = GetTabOrder(ui.tabsRecovery);
|
|
||||||
QWidget* pWidget3 = new QWidget();
|
QWidget* pWidget3 = new QWidget();
|
||||||
pWidget3->setLayout(ui.gridLayout_10);
|
pWidget3->setLayout(ui.gridLayout_10);
|
||||||
ui.gridLayout_24->addWidget(pWidget3, 1, 0);
|
ui.gridLayout_24->addWidget(pWidget3, 1, 0);
|
||||||
QWidget* pWidget4 = new QWidget();
|
QWidget* pWidget4 = new QWidget();
|
||||||
pWidget4->setLayout(ui.gridLayout_56);
|
pWidget4->setLayout(ui.gridLayout_56);
|
||||||
ui.gridLayout_24->addWidget(pWidget4, 2, 0);
|
ui.gridLayout_24->addWidget(pWidget4, 2, 0);
|
||||||
RestoreTabOrder(tabOrder);
|
|
||||||
delete ui.tabsRecovery;
|
delete ui.tabsRecovery;
|
||||||
ui.gridLayout_24->setContentsMargins(0, 0, 0, 0);
|
ui.gridLayout_24->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -357,7 +307,6 @@ COptionsWindow::COptionsWindow(const QSharedPointer<CSbieIni>& pBox, const QStri
|
||||||
if (iOptionLayout == 1)
|
if (iOptionLayout == 1)
|
||||||
{
|
{
|
||||||
// merge stop tabs
|
// merge stop tabs
|
||||||
tabOrder = GetTabOrder(ui.tabsStop);
|
|
||||||
QWidget* pWidget1 = new QWidget();
|
QWidget* pWidget1 = new QWidget();
|
||||||
pWidget1->setLayout(ui.gridLayout_57);
|
pWidget1->setLayout(ui.gridLayout_57);
|
||||||
ui.gridLayout_17->addWidget(pWidget1, 1, 0);
|
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->setVisible(false);
|
||||||
ui.lblStopOpt->setProperty("hidden", true);
|
ui.lblStopOpt->setProperty("hidden", true);
|
||||||
ui.gridLayout_17->addWidget(pWidget3, 3, 0);
|
ui.gridLayout_17->addWidget(pWidget3, 3, 0);
|
||||||
RestoreTabOrder(tabOrder);
|
|
||||||
delete ui.tabsStop;
|
delete ui.tabsStop;
|
||||||
ui.gridLayout_17->setContentsMargins(0, 0, 0, 0);
|
ui.gridLayout_17->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -718,6 +666,8 @@ COptionsWindow::COptionsWindow(const QSharedPointer<CSbieIni>& pBox, const QStri
|
||||||
this->addAction(pSetTree);
|
this->addAction(pSetTree);
|
||||||
}
|
}
|
||||||
m_pSearch->setPlaceholderText(tr("Search for options"));
|
m_pSearch->setPlaceholderText(tr("Search for options"));
|
||||||
|
|
||||||
|
SetTabOrder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void COptionsWindow::ApplyIniEditFont()
|
void COptionsWindow::ApplyIniEditFont()
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <qfontdialog.h>
|
#include <qfontdialog.h>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include "Helpers/TabOrder.h"
|
||||||
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -628,6 +629,8 @@ CSettingsWindow::CSettingsWindow(QWidget* parent)
|
||||||
this->addAction(pSetTree);
|
this->addAction(pSetTree);
|
||||||
}
|
}
|
||||||
m_pSearch->setPlaceholderText(tr("Search for settings"));
|
m_pSearch->setPlaceholderText(tr("Search for settings"));
|
||||||
|
|
||||||
|
SetTabOrder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSettingsWindow::ApplyIniEditFont()
|
void CSettingsWindow::ApplyIniEditFont()
|
||||||
|
|
Loading…
Reference in New Issue