Add helper for setting tab orders automatically
The helper functions are put into separate files under the Helpers folder. The helper is used in OptionsWindow and SettingsWindow. The helper sets the tab order of a widget using its row and column number in the grid layout. The tab orders are assigned first from left to right, then from top to bottom. If in the future a different custom type of layout is used, or a container other than QTabWidget is used, then the helper functions may need to be changed.
This commit is contained in:
parent
2fe4d71352
commit
125828e830
|
@ -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