Files
libreoffice/vcl/qt5/QtBuilder.cxx
Michael Weghorn 4d91b67e1f tdf#130857 qt weld: Evaluate button box orientation
Set orientation to vertical if that's specified
in the .ui file instead of using the default of
horizontal.

This is used by the button box on the right hand side
of the "Tools" -> "XML Filter Settings" dialog.

Change-Id: I64460037649dcd24897c7a5d7148430836702edc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178064
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-12-08 01:22:39 +01:00

743 lines
26 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <QtBuilder.hxx>
#include <QtDoubleSpinBox.hxx>
#include <QtExpander.hxx>
#include <QtInstanceLinkButton.hxx>
#include <QtInstanceMessageDialog.hxx>
#include <QtInstanceNotebook.hxx>
#include <QtTools.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/qt/QtUtils.hxx>
#include <QtGui/QStandardItemModel>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QLayout>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QProgressBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QRadioButton>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QTreeView>
namespace
{
QString convertAccelerator(const OUString& rText)
{
// preserve literal '&'s and use '&' instead of '_' for the accelerator
return toQString(rText.replaceAll("&", "&&").replace('_', '&'));
}
}
QtBuilder::QtBuilder(QObject* pParent, std::u16string_view sUIRoot, const OUString& rUIFile)
: WidgetBuilder(sUIRoot, rUIFile, false)
{
processUIFile(pParent);
}
QtBuilder::~QtBuilder() {}
QObject* QtBuilder::get_by_name(std::u16string_view sID)
{
for (auto const& child : m_aChildren)
{
if (child.m_sID == sID)
return child.m_pWindow;
}
return nullptr;
}
void QtBuilder::insertComboBoxOrListBoxItems(QObject* pObject, stringmap& rMap,
const std::vector<ComboBoxTextItem>& rItems)
{
if (QComboBox* pComboBox = qobject_cast<QComboBox*>(pObject))
{
for (const ComboBoxTextItem& rItem : rItems)
{
QVariant aUserData;
if (!rItem.m_sId.isEmpty())
aUserData = QVariant::fromValue(toQString(rItem.m_sId));
pComboBox->addItem(toQString(rItem.m_sItem), aUserData);
}
const int nActiveId = BuilderBase::extractActive(rMap);
pComboBox->setCurrentIndex(nActiveId);
return;
}
assert(false && "list boxes are not supported yet");
}
QObject* QtBuilder::insertObject(QObject* pParent, const OUString& rClass, std::string_view sType,
const OUString& rID, stringmap& rProps, stringmap&, stringmap&)
{
QObject* pCurrentChild = nullptr;
pCurrentChild = makeObject(pParent, rClass, sType, rID, rProps);
setProperties(pCurrentChild, rProps);
rProps.clear();
return pCurrentChild;
}
QObject* QtBuilder::makeObject(QObject* pParent, std::u16string_view sName, std::string_view sType,
const OUString& sID, stringmap& rMap)
{
// ignore placeholders
if (sName.empty())
return nullptr;
// nothing to do for these
if (sName == u"GtkCellRendererText" || sName == u"GtkTreeSelection")
return nullptr;
QWidget* pParentWidget = qobject_cast<QWidget*>(pParent);
QLayout* pParentLayout = qobject_cast<QLayout*>(pParent);
QObject* pObject = nullptr;
// in case a QLayout is created, an additional QWidget parent
// will also be created because that is needed for QtInstanceContainer
QWidget* pLayoutParentWidget = nullptr;
if (sName == u"GtkMessageDialog")
{
pObject = new QMessageBox(pParentWidget);
}
else if (sName == u"GtkBox")
{
// for a QMessageBox, return the existing layout instead of creating a new one
if (QMessageBox* pMessageBox = qobject_cast<QMessageBox*>(pParent))
{
pObject = pMessageBox->layout();
assert(pObject && "QMessageBox has no layout");
}
else
{
QWidget* pBoxParentWidget = pParentWidget;
// Unless this is the direct GtkBox child of a GtkDialog, create a parent widget
// that can be used to create a QtInstanceContainer for this box
if (!qobject_cast<QDialog*>(pParentWidget))
{
pLayoutParentWidget = new QWidget(pParentWidget);
pBoxParentWidget = pLayoutParentWidget;
}
const bool bVertical = hasOrientationVertical(rMap);
if (bVertical)
pObject = new QVBoxLayout(pBoxParentWidget);
else
pObject = new QHBoxLayout(pBoxParentWidget);
}
}
else if (sName == u"GtkButtonBox")
{
QWidget* pTopLevel = windowForObject(pParent);
if (QMessageBox* pMessageBox = qobject_cast<QMessageBox*>(pTopLevel))
{
// for a QMessageBox, return the existing button box instead of creating a new one
QDialogButtonBox* pButtonBox = findButtonBox(pMessageBox);
assert(pButtonBox && "Could not find QMessageBox's button box");
pObject = pButtonBox;
// skip adding to layout below, button box is already contained in dialog
pParentLayout = nullptr;
}
else
{
QDialogButtonBox* pButtonBox = new QDialogButtonBox(pParentWidget);
if (hasOrientationVertical(rMap))
pButtonBox->setOrientation(Qt::Vertical);
pObject = pButtonBox;
}
}
else if (sName == u"GtkButton")
{
if (QDialogButtonBox* pButtonBox = qobject_cast<QDialogButtonBox*>(pParentWidget))
{
pObject = pButtonBox->addButton("", QDialogButtonBox::NoRole);
// for message boxes, avoid implicit standard buttons in addition to those explicitly added
if (QMessageBox* pMessageBox = qobject_cast<QMessageBox*>(pParentWidget->window()))
pMessageBox->setStandardButtons(QMessageBox::NoButton);
}
else
{
pObject = new QPushButton(pParentWidget);
}
}
else if (sName == u"GtkCheckButton")
{
pObject = new QCheckBox(pParentWidget);
}
else if (sName == u"GtkComboBoxText")
{
QComboBox* pComboBox = new QComboBox(pParentWidget);
pComboBox->setEditable(extractEntry(rMap));
pObject = pComboBox;
}
else if (sName == u"GtkDialog")
{
pObject = new QDialog(pParentWidget);
}
else if (sName == u"GtkDrawingArea")
{
pObject = new QLabel(pParentWidget);
}
else if (sName == u"GtkEntry")
{
QLineEdit* pLineEdit = new QLineEdit(pParentWidget);
auto aIt = rMap.find(u"visibility"_ustr);
if (aIt != rMap.end() && !toBool(aIt->second))
pLineEdit->setEchoMode(QLineEdit::Password);
pObject = pLineEdit;
}
else if (sName == u"GtkExpander")
{
pObject = new QtExpander(pParentWidget);
}
else if (sName == u"GtkFrame")
{
pObject = new QGroupBox(pParentWidget);
}
else if (sName == u"GtkGrid")
{
pLayoutParentWidget = new QWidget(pParentWidget);
pObject = new QGridLayout(pLayoutParentWidget);
}
else if (sName == u"GtkImage")
{
QLabel* pLabel = new QLabel(pParentWidget);
const OUString sIconName = extractIconName(rMap);
if (!sIconName.isEmpty())
{
const Image aImage = loadThemeImage(sIconName);
pLabel->setPixmap(toQPixmap(aImage));
}
pObject = pLabel;
}
else if (sName == u"GtkLabel")
{
QLabel* pLabel = new QLabel(pParentWidget);
setLabelProperties(*pLabel, rMap);
extractMnemonicWidget(sID, rMap);
pObject = pLabel;
}
else if (sName == u"GtkLevelBar" || sName == u"GtkProgressBar")
{
QProgressBar* pProgressBar = new QProgressBar(pParentWidget);
// don't show text (progress in percent) by default
pProgressBar->setTextVisible(false);
pObject = pProgressBar;
}
else if (sName == u"GtkLinkButton")
{
QtHyperlinkLabel* pLabel = new QtHyperlinkLabel(pParentWidget);
if (rMap.contains(u"label"_ustr))
pLabel->setDisplayText(toQString(rMap[u"label"_ustr]));
if (rMap.contains(u"uri"_ustr))
pLabel->setUri(toQString(rMap[u"uri"_ustr]));
pObject = pLabel;
}
else if (sName == u"GtkNotebook")
{
pObject = new QTabWidget(pParentWidget);
}
else if (sName == u"GtkRadioButton")
{
pObject = new QRadioButton(pParentWidget);
}
else if (sName == u"GtkScrolledWindow")
{
pObject = new QScrollArea(pParentWidget);
}
else if (sName == u"GtkSeparator")
{
const bool bVertical = hasOrientationVertical(rMap);
QFrame* pFrame = new QFrame(pParentWidget);
pFrame->setFrameShape(bVertical ? QFrame::VLine : QFrame::HLine);
pObject = pFrame;
}
else if (sName == u"GtkSpinButton")
{
QtDoubleSpinBox* pSpinBox = new QtDoubleSpinBox(pParentWidget);
setSpinButtonProperties(*pSpinBox, rMap);
pObject = pSpinBox;
}
else if (sName == u"GtkTextView")
{
pObject = new QPlainTextEdit(pParentWidget);
}
else if (sName == u"GtkTreeView")
{
QTreeView* pTreeView = new QTreeView(pParentWidget);
pTreeView->setModel(new QStandardItemModel(pTreeView));
pTreeView->setHeaderHidden(!extractHeadersVisible(rMap));
pTreeView->setRootIsDecorated(extractShowExpanders(rMap));
pObject = pTreeView;
}
else if (sName == u"GtkTreeViewColumn")
{
QTreeView* pTreeView = qobject_cast<QTreeView*>(pParentWidget);
assert(pTreeView && "Tree view column doesn't have a tree view parent");
QStandardItemModel* pModel = qobject_cast<QStandardItemModel*>(pTreeView->model());
assert(pModel && "Tree view doesn't have QStandardItemModel set");
const int nCol = pModel->columnCount();
pModel->insertColumn(nCol);
pModel->setHeaderData(nCol, Qt::Horizontal, toQString(extractTitle(rMap)));
// nothing else to do, return tree view parent for the widget
return pTreeView;
}
else
{
SAL_WARN("vcl.qt", "Widget type not supported yet: "
<< OUStringToOString(sName, RTL_TEXTENCODING_UTF8));
assert(false && "Widget type not supported yet");
}
QWidget* pWidget = qobject_cast<QWidget*>(pObject);
if (!pWidget)
pWidget = pLayoutParentWidget;
QTabWidget* pParentTabWidget = qobject_cast<QTabWidget*>(pParentWidget);
if (pParentTabWidget)
{
// remove QTabWidget child widget, set via QTabWidget::addTab instead
assert(pWidget);
pWidget->setParent(nullptr);
// initially, add tab with empty label, QtBuilder::applyTabChildProperties will evaluate actual one
pParentTabWidget->addTab(pWidget, QStringLiteral());
// unset pParentWidget to not create a layout below
pParentWidget = nullptr;
}
else if (QtExpander* pExpander = qobject_cast<QtExpander*>(pParentWidget))
{
// set the content (not the label) child as the expander's widget
if (sType != "label")
{
pExpander->setContentWidget(pWidget);
// erase "visible" property, QtExpander shows/hides the widget as needed
rMap.erase("visible");
}
}
if (pWidget)
{
if (!pParentLayout && pParentWidget)
{
// if the parent is a widget, use the widget's layout, and ensure it has one set
pParentLayout = pParentWidget->layout();
if (!pParentLayout)
pParentLayout = new QVBoxLayout(pParentWidget);
}
// add widget to parent layout
if (pParentLayout)
pParentLayout->addWidget(pWidget);
QtInstanceWidget::setHelpId(*pWidget, getHelpRoot() + sID);
pWidget->setToolTip(toQString(extractTooltipText(rMap)));
pWidget->setVisible(extractVisible(rMap));
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
// Set GtkBuilder ID as accessible ID
pWidget->setAccessibleIdentifier(toQString(sID));
#endif
}
else if (QLayout* pLayout = qobject_cast<QLayout*>(pObject))
{
// add layout to parent layout
if (QBoxLayout* pParentBoxLayout = qobject_cast<QBoxLayout*>(pParentLayout))
pParentBoxLayout->addLayout(pLayout);
else if (QGridLayout* pParentGridLayout = qobject_cast<QGridLayout*>(pParentLayout))
pParentGridLayout->addLayout(pLayout, pParentGridLayout->rowCount(), 0);
}
m_aChildren.emplace_back(sID, pObject);
return pObject;
}
void QtBuilder::tweakInsertedChild(QObject* pParent, QObject* pCurrentChild, std::string_view sType,
std::string_view sInternalChild)
{
if (sInternalChild == "entry" && qobject_cast<QComboBox*>(pParent))
{
// an editable GtkComboBox has an internal GtkEntry child,
// but QComboBox doesn't need a separate widget for it, so
// delete it
deleteObject(pCurrentChild);
}
if (sType == "label")
{
if (QLabel* pLabel = qobject_cast<QLabel*>(pCurrentChild))
{
if (QGroupBox* pGroupBox = qobject_cast<QGroupBox*>(pParent))
{
// GtkFrame has a `child-type="label"` child for the GtkFrame label
// in the GtkBuilder .ui file, s. https://docs.gtk.org/gtk3/class.Frame.html
// For QGroupBox, the title can be set directly. Therefore, take over the
// title from the label and delete the separate label widget again
pGroupBox->setTitle(pLabel->text());
deleteObject(pLabel);
}
else if (QtExpander* pExpander = qobject_cast<QtExpander*>(pParent))
{
// GtkExpander has a `child-type="label"` child for the expander label
// in the GtkBuilder .ui file, s. https://docs.gtk.org/gtk3/class.Expander.html
// For QtExpander, the (button) text can be set directly. Therefore, take over
// text from the label and delete the separate label widget again
pExpander->setText(pLabel->text());
deleteObject(pLabel);
}
}
}
if (QDialog* pDialog = qobject_cast<QDialog*>(pCurrentChild))
{
// no action needed for QMessageBox, where the default button box is used
// and button click is handled in QtInstanceMessageDialog
if (!qobject_cast<QMessageBox*>(pDialog))
{
if (QDialogButtonBox* pButtonBox = findButtonBox(pDialog))
{
// ensure that button box is the last item in QDialog's layout
// (that seems to be implicitly the case for GtkDialog in GTK)
QLayout* pLayout = pDialog->layout();
assert(pLayout && "dialog has no layout");
pLayout->removeWidget(pButtonBox);
pLayout->addWidget(pButtonBox);
// connect button click handler
const QList<QAbstractButton*> aButtons = pButtonBox->buttons();
for (QAbstractButton* pButton : aButtons)
{
assert(pButton);
QObject::connect(pButton, &QAbstractButton::clicked, pDialog,
[pDialog, pButton] {
QtInstanceDialog::handleButtonClick(*pDialog, *pButton);
});
}
}
}
}
}
void QtBuilder::setMnemonicWidget(const OUString& rLabelId, const OUString& rMnemonicWidgetId)
{
QLabel* pLabel = get<QLabel>(rLabelId);
QObject* pBuddy = get_by_name(rMnemonicWidgetId);
if (!pLabel || !pBuddy || !pBuddy->isWidgetType())
return;
pLabel->setBuddy(static_cast<QWidget*>(pBuddy));
}
void QtBuilder::setPriority(QObject*, int) { SAL_WARN("vcl.qt", "Ignoring priority"); }
void QtBuilder::setContext(QObject*, std::vector<vcl::EnumContext::Context>&&)
{
SAL_WARN("vcl.qt", "Ignoring context");
}
bool QtBuilder::isHorizontalTabControl(QObject* pObject)
{
QTabWidget* pTabWidget = qobject_cast<QTabWidget*>(pObject);
if (!pTabWidget)
return false;
const QTabWidget::TabPosition ePosition = pTabWidget->tabPosition();
return ePosition == QTabWidget::TabPosition::North
|| ePosition == QTabWidget::TabPosition::South;
}
QMenu* QtBuilder::createMenu(const OUString&)
{
assert(false && "Not implemented yet");
return nullptr;
}
void QtBuilder::insertMenuObject(QMenu*, QMenu*, const OUString&, const OUString&, stringmap&,
stringmap&, accelmap&)
{
assert(false && "Not implemented yet");
}
void QtBuilder::applyAtkProperties(QObject* pObject, const stringmap& rProperties, bool)
{
if (!pObject || !pObject->isWidgetType())
return;
QWidget* pWidget = static_cast<QWidget*>(pObject);
for (auto const & [ rKey, rValue ] : rProperties)
{
if (rKey == "AtkObject::accessible-description")
pWidget->setAccessibleDescription(toQString(rValue));
else if (rKey == "AtkObject::accessible-name")
pWidget->setAccessibleName(toQString(rValue));
}
}
void QtBuilder::applyGridPackingProperties(QWidget* pCurrentChild, QGridLayout& rGrid,
const stringmap& rPackingProperties)
{
assert(pCurrentChild);
// properties not set when there's no explicit GtkGrid in the .ui file,
// like for the QGridLayout that's the (implicit) layout of a QMessageBox
if (!rPackingProperties.contains(u"left-attach"_ustr)
|| !rPackingProperties.contains(u"top-attach"_ustr))
return;
const sal_Int32 nColumn = rPackingProperties.at(u"left-attach"_ustr).toInt32();
const sal_Int32 nRow = rPackingProperties.at(u"top-attach"_ustr).toInt32();
auto aWidthIt = rPackingProperties.find(u"width"_ustr);
sal_Int32 nColumnSpan = (aWidthIt == rPackingProperties.end()) ? 1 : aWidthIt->second.toInt32();
auto aHeightIt = rPackingProperties.find(u"height"_ustr);
sal_Int32 nRowSpan = (aHeightIt == rPackingProperties.end()) ? 1 : aHeightIt->second.toInt32();
rGrid.removeWidget(pCurrentChild);
rGrid.addWidget(pCurrentChild, nRow, nColumn, nRowSpan, nColumnSpan);
}
void QtBuilder::applyPackingProperties(QObject* pCurrentChild, QObject* pParent,
const stringmap& rPackingProperties)
{
if (!pCurrentChild)
return;
QWidget* pWidget = nullptr;
if (pCurrentChild->isWidgetType())
pWidget = static_cast<QWidget*>(pCurrentChild);
else
{
QObject* pParentObject = pCurrentChild->parent();
assert(pParent && "Non-widget (i.e. layout) has no parent");
if (pParentObject->isWidgetType())
pWidget = static_cast<QWidget*>(pParentObject);
}
if (!pWidget)
return;
// check parent's parent, due to extra QWidget parents for layouts
if (QGridLayout* pGrid = qobject_cast<QGridLayout*>(pParent))
applyGridPackingProperties(pWidget, *pGrid, rPackingProperties);
else
SAL_WARN("vcl.qt", "QtBuilder::applyPackingProperties not yet implemented for this case");
}
void QtBuilder::applyTabChildProperties(QObject* pParent, const std::vector<OUString>& rIDs,
std::vector<vcl::EnumContext::Context>&,
stringmap& rProperties, stringmap&)
{
QTabWidget* pTabWidget = qobject_cast<QTabWidget*>(pParent);
assert(pTabWidget && "parent must be a QTabWidget");
// set ID and label for the last inserted tab
assert(rProperties.contains(u"label"_ustr) && "Tab has no label");
QtInstanceNotebook::setTabIdAndLabel(*pTabWidget, pTabWidget->count() - 1, rIDs.front(),
rProperties.at(u"label"_ustr));
}
void QtBuilder::set_response(std::u16string_view sID, short nResponse)
{
QPushButton* pPushButton = get<QPushButton>(sID);
assert(pPushButton);
pPushButton->setProperty(QtInstanceMessageDialog::PROPERTY_VCL_RESPONSE_CODE, int(nResponse));
}
void QtBuilder::deleteObject(QObject* pObject)
{
if (pObject->isWidgetType())
static_cast<QWidget*>(pObject)->hide();
pObject->deleteLater();
}
void QtBuilder::setProperties(QObject* pObject, stringmap& rProps)
{
if (QMessageBox* pMessageBox = qobject_cast<QMessageBox*>(pObject))
{
for (auto const & [ rKey, rValue ] : rProps)
{
if (rKey == u"text")
{
pMessageBox->setText(toQString(rValue));
}
else if (rKey == u"title")
{
pMessageBox->setWindowTitle(toQString(rValue));
}
else if (rKey == u"secondary-text")
{
pMessageBox->setInformativeText(toQString(rValue));
}
else if (rKey == u"message-type")
{
if (rValue == u"error")
pMessageBox->setIcon(QMessageBox::Critical);
else if (rValue == u"info")
pMessageBox->setIcon(QMessageBox::Information);
else if (rValue == u"question")
pMessageBox->setIcon(QMessageBox::Question);
else if (rValue == u"warning")
pMessageBox->setIcon(QMessageBox::Warning);
else
assert(false && "Unhandled message-type");
}
}
}
else if (qobject_cast<QCheckBox*>(pObject) || qobject_cast<QRadioButton*>(pObject))
{
QAbstractButton* pButton = static_cast<QAbstractButton*>(pObject);
for (auto const & [ rKey, rValue ] : rProps)
{
if (rKey == u"active")
pButton->setChecked(toBool(rValue));
else if (rKey == u"label")
pButton->setText(convertAccelerator(rValue));
}
}
else if (QDialog* pDialog = qobject_cast<QDialog*>(pObject))
{
for (auto const & [ rKey, rValue ] : rProps)
{
if (rKey == u"modal")
pDialog->setModal(toBool(rValue));
else if (rKey == u"title")
pDialog->setWindowTitle(toQString(rValue));
}
}
else if (QPlainTextEdit* pTextEdit = qobject_cast<QPlainTextEdit*>(pObject))
{
for (auto const & [ rKey, rValue ] : rProps)
{
if (rKey == u"accepts-tab")
pTextEdit->setTabChangesFocus(!toBool(rValue));
}
}
else if (QPushButton* pButton = qobject_cast<QPushButton*>(pObject))
{
for (auto const & [ rKey, rValue ] : rProps)
{
if (rKey == u"image")
{
QLabel* pImageLabel = get<QLabel>(rValue);
assert(pImageLabel && "Button has non-existent image set");
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
pButton->setIcon(QIcon(pImageLabel->pixmap()));
#else
pButton->setIcon(QIcon(pImageLabel->pixmap(Qt::ReturnByValue)));
#endif
// parentless GtkImage in .ui file is only used for setting button
// image, so the object is no longer needed after doing so
if (!pImageLabel->parent())
deleteObject(pImageLabel);
}
else if (rKey == u"label")
{
pButton->setText(convertAccelerator(rValue));
}
}
}
}
void QtBuilder::setLabelProperties(QLabel& rLabel, stringmap& rProps)
{
for (auto const & [ rKey, rValue ] : rProps)
{
if (rKey == u"label")
rLabel.setText(convertAccelerator(rValue));
else if (rKey == u"wrap")
rLabel.setWordWrap(toBool(rValue));
}
}
void QtBuilder::setSpinButtonProperties(QDoubleSpinBox& rSpinBox, stringmap& rProps)
{
auto aDigitsIt = rProps.find(u"digits"_ustr);
sal_Int32 nDigits = (aDigitsIt != rProps.end()) ? aDigitsIt->second.toInt32() : 0;
rSpinBox.setDecimals(nDigits);
auto aAdjustmentIt = rProps.find("adjustment");
if (aAdjustmentIt != rProps.end())
{
const Adjustment* pAdjustment = get_adjustment_by_name(aAdjustmentIt->second);
assert(pAdjustment && "referenced adjustment doesn't exist");
for (auto const & [ rKey, rValue ] : *pAdjustment)
{
if (rKey == u"upper")
rSpinBox.setMaximum(rValue.toDouble());
else if (rKey == u"lower")
rSpinBox.setMinimum(rValue.toDouble());
else if (rKey == "value")
rSpinBox.setValue(rValue.toDouble());
else if (rKey == "step-increment")
rSpinBox.setSingleStep(rValue.toDouble());
}
}
}
QWidget* QtBuilder::windowForObject(QObject* pObject)
{
if (QWidget* pWidget = qobject_cast<QWidget*>(pObject))
return pWidget->window();
if (QLayout* pLayout = qobject_cast<QLayout*>(pObject))
{
if (QWidget* pParentWidget = pLayout->parentWidget())
return pParentWidget->window();
}
return nullptr;
}
QDialogButtonBox* QtBuilder::findButtonBox(QDialog* pDialog)
{
assert(pDialog);
QLayout* pLayout = pDialog->layout();
if (!pLayout)
return nullptr;
for (int i = 0; i < pLayout->count(); i++)
{
QLayoutItem* pItem = pLayout->itemAt(i);
if (QWidget* pItemWidget = pItem->widget())
{
if (QDialogButtonBox* pButtonBox = qobject_cast<QDialogButtonBox*>(pItemWidget))
return pButtonBox;
}
}
return nullptr;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */