2024-11-18 09:33:05 +01:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
2024-09-25 09:48:09 +02:00
|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
|
2024-11-27 17:39:02 +01:00
|
|
|
#include <QtDoubleSpinBox.hxx>
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
#include <QtExpander.hxx>
|
2024-10-25 20:41:48 +02:00
|
|
|
#include <QtInstanceLinkButton.hxx>
|
2024-09-25 12:10:12 +02:00
|
|
|
#include <QtInstanceMessageDialog.hxx>
|
2024-11-10 18:54:28 +01:00
|
|
|
#include <QtInstanceNotebook.hxx>
|
2024-09-25 09:48:09 +02:00
|
|
|
#include <QtTools.hxx>
|
|
|
|
|
|
|
|
#include <rtl/ustrbuf.hxx>
|
2024-10-24 00:19:56 +02:00
|
|
|
#include <vcl/qt/QtUtils.hxx>
|
2024-09-25 09:48:09 +02:00
|
|
|
|
2024-11-29 15:44:47 +01:00
|
|
|
#include <QtGui/QStandardItemModel>
|
2024-10-02 17:36:21 +02:00
|
|
|
#include <QtWidgets/QCheckBox>
|
2024-10-22 18:19:45 +02:00
|
|
|
#include <QtWidgets/QComboBox>
|
2024-09-25 09:48:09 +02:00
|
|
|
#include <QtWidgets/QDialog>
|
|
|
|
#include <QtWidgets/QDialogButtonBox>
|
2024-10-04 10:38:32 +02:00
|
|
|
#include <QtWidgets/QGroupBox>
|
2024-09-28 00:07:28 +02:00
|
|
|
#include <QtWidgets/QLabel>
|
2024-10-04 16:36:16 +02:00
|
|
|
#include <QtWidgets/QLineEdit>
|
2024-09-25 09:48:09 +02:00
|
|
|
#include <QtWidgets/QLayout>
|
2024-10-04 16:54:31 +02:00
|
|
|
#include <QtWidgets/QPlainTextEdit>
|
2024-10-29 21:13:26 +01:00
|
|
|
#include <QtWidgets/QProgressBar>
|
2024-09-25 09:48:09 +02:00
|
|
|
#include <QtWidgets/QPushButton>
|
2024-10-25 13:21:55 +02:00
|
|
|
#include <QtWidgets/QRadioButton>
|
2024-10-04 16:47:55 +02:00
|
|
|
#include <QtWidgets/QScrollArea>
|
2024-11-09 20:44:42 +01:00
|
|
|
#include <QtWidgets/QTabWidget>
|
2024-11-09 00:28:06 +01:00
|
|
|
#include <QtWidgets/QTreeView>
|
2024-09-25 09:48:09 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-10-24 18:22:43 +02:00
|
|
|
void QtBuilder::insertComboBoxOrListBoxItems(QObject* pObject, stringmap& rMap,
|
|
|
|
const std::vector<ComboBoxTextItem>& rItems)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-10-24 18:22:43 +02:00
|
|
|
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");
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
QObject* QtBuilder::insertObject(QObject* pParent, const OUString& rClass, std::string_view sType,
|
2024-11-23 20:54:47 +01:00
|
|
|
const OUString& rID, stringmap& rProps, stringmap&, stringmap&)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
|
|
|
QObject* pCurrentChild = nullptr;
|
|
|
|
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
pCurrentChild = makeObject(pParent, rClass, sType, rID, rProps);
|
2024-09-25 09:48:09 +02:00
|
|
|
|
|
|
|
setProperties(pCurrentChild, rProps);
|
|
|
|
|
|
|
|
rProps.clear();
|
|
|
|
|
|
|
|
return pCurrentChild;
|
|
|
|
}
|
|
|
|
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
QObject* QtBuilder::makeObject(QObject* pParent, std::u16string_view sName, std::string_view sType,
|
|
|
|
const OUString& sID, stringmap& rMap)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-09-27 20:15:11 +02:00
|
|
|
// ignore placeholders
|
|
|
|
if (sName.empty())
|
|
|
|
return nullptr;
|
|
|
|
|
2024-11-29 15:44:47 +01:00
|
|
|
// nothing to do for these
|
|
|
|
if (sName == u"GtkCellRendererText" || sName == u"GtkTreeSelection")
|
|
|
|
return nullptr;
|
|
|
|
|
2024-09-25 09:48:09 +02:00
|
|
|
QWidget* pParentWidget = qobject_cast<QWidget*>(pParent);
|
2024-09-27 21:41:43 +02:00
|
|
|
QLayout* pParentLayout = qobject_cast<QLayout*>(pParent);
|
2024-09-25 09:48:09 +02:00
|
|
|
|
|
|
|
QObject* pObject = nullptr;
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
// in case a QLayout is created, an additional QWidget parent
|
|
|
|
// will also be created because that is needed for QtInstanceContainer
|
|
|
|
QWidget* pLayoutParentWidget = nullptr;
|
2024-09-25 09:48:09 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
{
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-09-25 09:48:09 +02:00
|
|
|
const bool bVertical = hasOrientationVertical(rMap);
|
|
|
|
if (bVertical)
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
pObject = new QVBoxLayout(pBoxParentWidget);
|
2024-09-25 09:48:09 +02:00
|
|
|
else
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
pObject = new QHBoxLayout(pBoxParentWidget);
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
2024-09-27 21:41:43 +02:00
|
|
|
|
|
|
|
// skip adding to layout below, button box is already contained in dialog
|
|
|
|
pParentLayout = nullptr;
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-12-07 22:08:14 +01:00
|
|
|
QDialogButtonBox* pButtonBox = new QDialogButtonBox(pParentWidget);
|
|
|
|
if (hasOrientationVertical(rMap))
|
|
|
|
pButtonBox->setOrientation(Qt::Vertical);
|
|
|
|
pObject = pButtonBox;
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2024-10-02 17:36:21 +02:00
|
|
|
else if (sName == u"GtkCheckButton")
|
|
|
|
{
|
|
|
|
pObject = new QCheckBox(pParentWidget);
|
|
|
|
}
|
2024-10-22 18:19:45 +02:00
|
|
|
else if (sName == u"GtkComboBoxText")
|
|
|
|
{
|
2024-10-24 01:42:13 +02:00
|
|
|
QComboBox* pComboBox = new QComboBox(pParentWidget);
|
|
|
|
pComboBox->setEditable(extractEntry(rMap));
|
|
|
|
pObject = pComboBox;
|
2024-10-22 18:19:45 +02:00
|
|
|
}
|
2024-09-28 00:07:28 +02:00
|
|
|
else if (sName == u"GtkDialog")
|
|
|
|
{
|
|
|
|
pObject = new QDialog(pParentWidget);
|
|
|
|
}
|
2024-11-06 21:51:46 +01:00
|
|
|
else if (sName == u"GtkDrawingArea")
|
|
|
|
{
|
|
|
|
pObject = new QLabel(pParentWidget);
|
|
|
|
}
|
2024-10-04 16:36:16 +02:00
|
|
|
else if (sName == u"GtkEntry")
|
|
|
|
{
|
2024-10-29 21:27:50 +01:00
|
|
|
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;
|
2024-10-04 16:36:16 +02:00
|
|
|
}
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
else if (sName == u"GtkExpander")
|
|
|
|
{
|
|
|
|
pObject = new QtExpander(pParentWidget);
|
|
|
|
}
|
2024-10-04 10:38:32 +02:00
|
|
|
else if (sName == u"GtkFrame")
|
|
|
|
{
|
|
|
|
pObject = new QGroupBox(pParentWidget);
|
|
|
|
}
|
2024-10-21 18:16:22 +02:00
|
|
|
else if (sName == u"GtkGrid")
|
|
|
|
{
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
pLayoutParentWidget = new QWidget(pParentWidget);
|
|
|
|
pObject = new QGridLayout(pLayoutParentWidget);
|
2024-10-21 18:16:22 +02:00
|
|
|
}
|
2024-10-25 20:26:15 +02:00
|
|
|
else if (sName == u"GtkImage")
|
|
|
|
{
|
2024-10-28 22:29:25 +01:00
|
|
|
QLabel* pLabel = new QLabel(pParentWidget);
|
|
|
|
const OUString sIconName = extractIconName(rMap);
|
|
|
|
if (!sIconName.isEmpty())
|
|
|
|
{
|
|
|
|
const Image aImage = loadThemeImage(sIconName);
|
|
|
|
pLabel->setPixmap(toQPixmap(aImage));
|
|
|
|
}
|
|
|
|
pObject = pLabel;
|
2024-10-25 20:26:15 +02:00
|
|
|
}
|
2024-09-28 00:07:28 +02:00
|
|
|
else if (sName == u"GtkLabel")
|
|
|
|
{
|
2024-11-08 22:19:59 +01:00
|
|
|
QLabel* pLabel = new QLabel(pParentWidget);
|
|
|
|
setLabelProperties(*pLabel, rMap);
|
2024-10-04 22:56:05 +02:00
|
|
|
extractMnemonicWidget(sID, rMap);
|
2024-11-08 22:19:59 +01:00
|
|
|
pObject = pLabel;
|
2024-09-28 00:07:28 +02:00
|
|
|
}
|
2024-10-30 09:54:55 +01:00
|
|
|
else if (sName == u"GtkLevelBar" || sName == u"GtkProgressBar")
|
2024-10-29 21:13:26 +01:00
|
|
|
{
|
|
|
|
QProgressBar* pProgressBar = new QProgressBar(pParentWidget);
|
2024-10-30 09:54:55 +01:00
|
|
|
// don't show text (progress in percent) by default
|
2024-10-29 21:13:26 +01:00
|
|
|
pProgressBar->setTextVisible(false);
|
|
|
|
pObject = pProgressBar;
|
|
|
|
}
|
2024-10-25 20:41:48 +02:00
|
|
|
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))
|
2024-10-31 23:25:21 +01:00
|
|
|
pLabel->setUri(toQString(rMap[u"uri"_ustr]));
|
2024-10-25 20:41:48 +02:00
|
|
|
|
|
|
|
pObject = pLabel;
|
|
|
|
}
|
2024-11-09 22:03:16 +01:00
|
|
|
else if (sName == u"GtkNotebook")
|
|
|
|
{
|
|
|
|
pObject = new QTabWidget(pParentWidget);
|
|
|
|
}
|
2024-10-25 13:21:55 +02:00
|
|
|
else if (sName == u"GtkRadioButton")
|
|
|
|
{
|
|
|
|
pObject = new QRadioButton(pParentWidget);
|
|
|
|
}
|
2024-10-04 16:47:55 +02:00
|
|
|
else if (sName == u"GtkScrolledWindow")
|
|
|
|
{
|
|
|
|
pObject = new QScrollArea(pParentWidget);
|
|
|
|
}
|
2024-11-06 21:32:59 +01:00
|
|
|
else if (sName == u"GtkSeparator")
|
|
|
|
{
|
|
|
|
const bool bVertical = hasOrientationVertical(rMap);
|
|
|
|
QFrame* pFrame = new QFrame(pParentWidget);
|
|
|
|
pFrame->setFrameShape(bVertical ? QFrame::VLine : QFrame::HLine);
|
|
|
|
pObject = pFrame;
|
|
|
|
}
|
2024-11-07 22:04:07 +01:00
|
|
|
else if (sName == u"GtkSpinButton")
|
|
|
|
{
|
2024-11-27 17:39:02 +01:00
|
|
|
QtDoubleSpinBox* pSpinBox = new QtDoubleSpinBox(pParentWidget);
|
2024-11-07 22:04:07 +01:00
|
|
|
setSpinButtonProperties(*pSpinBox, rMap);
|
|
|
|
pObject = pSpinBox;
|
|
|
|
}
|
2024-10-04 16:54:31 +02:00
|
|
|
else if (sName == u"GtkTextView")
|
|
|
|
{
|
|
|
|
pObject = new QPlainTextEdit(pParentWidget);
|
|
|
|
}
|
2024-11-09 00:28:06 +01:00
|
|
|
else if (sName == u"GtkTreeView")
|
|
|
|
{
|
2024-11-29 15:44:47 +01:00
|
|
|
QTreeView* pTreeView = new QTreeView(pParentWidget);
|
|
|
|
pTreeView->setModel(new QStandardItemModel(pTreeView));
|
2024-11-29 16:17:16 +01:00
|
|
|
pTreeView->setHeaderHidden(!extractHeadersVisible(rMap));
|
2024-11-29 16:38:33 +01:00
|
|
|
pTreeView->setRootIsDecorated(extractShowExpanders(rMap));
|
2024-11-29 15:44:47 +01:00
|
|
|
pObject = pTreeView;
|
|
|
|
}
|
|
|
|
else if (sName == u"GtkTreeViewColumn")
|
|
|
|
{
|
2024-12-07 21:04:49 +01:00
|
|
|
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;
|
2024-11-09 00:28:06 +01:00
|
|
|
}
|
2024-09-27 19:22:53 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
SAL_WARN("vcl.qt", "Widget type not supported yet: "
|
|
|
|
<< OUStringToOString(sName, RTL_TEXTENCODING_UTF8));
|
|
|
|
assert(false && "Widget type not supported yet");
|
|
|
|
}
|
2024-09-25 09:48:09 +02:00
|
|
|
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
QWidget* pWidget = qobject_cast<QWidget*>(pObject);
|
|
|
|
if (!pWidget)
|
|
|
|
pWidget = pLayoutParentWidget;
|
|
|
|
|
2024-11-10 18:54:28 +01:00
|
|
|
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());
|
2024-11-15 22:51:54 +01:00
|
|
|
// unset pParentWidget to not create a layout below
|
2024-11-10 18:54:28 +01:00
|
|
|
pParentWidget = nullptr;
|
|
|
|
}
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
2024-11-10 18:54:28 +01:00
|
|
|
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
if (pWidget)
|
2024-09-27 21:41:43 +02:00
|
|
|
{
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2024-09-28 22:19:53 +02:00
|
|
|
// add widget to parent layout
|
|
|
|
if (pParentLayout)
|
2024-09-27 21:41:43 +02:00
|
|
|
pParentLayout->addWidget(pWidget);
|
2024-09-28 22:19:53 +02:00
|
|
|
|
2024-10-04 14:41:29 +02:00
|
|
|
QtInstanceWidget::setHelpId(*pWidget, getHelpRoot() + sID);
|
|
|
|
|
2024-10-29 07:19:48 +01:00
|
|
|
pWidget->setToolTip(toQString(extractTooltipText(rMap)));
|
2024-10-11 23:05:32 +02:00
|
|
|
pWidget->setVisible(extractVisible(rMap));
|
|
|
|
|
2024-09-28 22:19:53 +02:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
|
|
|
// Set GtkBuilder ID as accessible ID
|
|
|
|
pWidget->setAccessibleIdentifier(toQString(sID));
|
|
|
|
#endif
|
2024-09-27 21:41:43 +02:00
|
|
|
}
|
2024-10-02 17:10:22 +02:00
|
|
|
else if (QLayout* pLayout = qobject_cast<QLayout*>(pObject))
|
|
|
|
{
|
|
|
|
// add layout to parent layout
|
|
|
|
if (QBoxLayout* pParentBoxLayout = qobject_cast<QBoxLayout*>(pParentLayout))
|
|
|
|
pParentBoxLayout->addLayout(pLayout);
|
2024-10-25 20:45:39 +02:00
|
|
|
else if (QGridLayout* pParentGridLayout = qobject_cast<QGridLayout*>(pParentLayout))
|
|
|
|
pParentGridLayout->addLayout(pLayout, pParentGridLayout->rowCount(), 0);
|
2024-10-02 17:10:22 +02:00
|
|
|
}
|
2024-09-27 21:41:43 +02:00
|
|
|
|
2024-09-25 09:48:09 +02:00
|
|
|
m_aChildren.emplace_back(sID, pObject);
|
|
|
|
|
|
|
|
return pObject;
|
|
|
|
}
|
|
|
|
|
2024-10-04 10:38:32 +02:00
|
|
|
void QtBuilder::tweakInsertedChild(QObject* pParent, QObject* pCurrentChild, std::string_view sType,
|
2024-10-24 01:42:13 +02:00
|
|
|
std::string_view sInternalChild)
|
2024-09-28 00:26:52 +02:00
|
|
|
{
|
2024-10-24 01:42:13 +02:00
|
|
|
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
|
2024-11-23 01:11:38 +01:00
|
|
|
deleteObject(pCurrentChild);
|
2024-10-24 01:42:13 +02:00
|
|
|
}
|
|
|
|
|
2024-10-04 10:38:32 +02:00
|
|
|
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());
|
2024-11-23 01:11:38 +01:00
|
|
|
deleteObject(pLabel);
|
2024-10-04 10:38:32 +02:00
|
|
|
}
|
tdf#130857 qt weld: Implement "GtkExpander" equivalent
Implement support for "GtkExpander" objects in .ui
files. As Qt doesn't seem to have any equivalent, add
a new QtExpander class that subclasses QWidget and
has a button that can be used to toggle visibility
of the widget that is the GtkExpander's [1] content child.
For a visual appearance similar to GtkExpander,
set an icon for the button ("go-down" and "go-next"
from the icon theme, which are arrows like the ones
shown on a GtkExpander, at least with the Breeze
icon theme).
In QtBuilder, implement handling for "GtkExpander"
objects:
* Create an instance of the new QtExpander
class.
* Identify the content child, which can be distinguished
from the label child by the fact that the latter
has a "label" child type set, see also previous
commit
Change-Id: I3e308a6642d72b55d0ccc597dac716b236c22d61
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Sat Nov 23 20:54:47 2024 +0100
tdf#130857 Pass child type to WidgetBuilder::insertObject
* Erase the "visible" property for the content child,
as otherwise the content widget would be initially
visible even if the expander is set to not be
expanded. (QtExpander takes care of this, so
ignore the property set in the .ui file.)
* For the label child in GtkExpander, simply take
over its text to QtExpander's button, then mark
the label for deletion, as it's not needed
otherwise.
Support for the "Document in Use" dialog that
has a GtkExpander and thuse makes use of this
will be declared in a separate commit.
[1] https://docs.gtk.org/gtk3/class.Expander.html
Change-Id: Id2366834cb542eba613ea087e70f3a812d20fa89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177193
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
2024-11-24 00:07:44 +01:00
|
|
|
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);
|
|
|
|
}
|
2024-10-04 10:38:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-28 00:26:52 +02:00
|
|
|
if (QDialog* pDialog = qobject_cast<QDialog*>(pCurrentChild))
|
|
|
|
{
|
2024-09-28 00:32:15 +02:00
|
|
|
// no action needed for QMessageBox, where the default button box is used
|
|
|
|
// and button click is handled in QtInstanceMessageDialog
|
2024-09-28 00:26:52 +02:00
|
|
|
if (!qobject_cast<QMessageBox*>(pDialog))
|
|
|
|
{
|
|
|
|
if (QDialogButtonBox* pButtonBox = findButtonBox(pDialog))
|
|
|
|
{
|
2024-09-28 00:32:15 +02:00
|
|
|
// ensure that button box is the last item in QDialog's layout
|
|
|
|
// (that seems to be implicitly the case for GtkDialog in GTK)
|
2024-09-28 00:26:52 +02:00
|
|
|
QLayout* pLayout = pDialog->layout();
|
|
|
|
assert(pLayout && "dialog has no layout");
|
|
|
|
pLayout->removeWidget(pButtonBox);
|
|
|
|
pLayout->addWidget(pButtonBox);
|
2024-09-28 00:32:15 +02:00
|
|
|
|
2024-10-04 12:50:10 +02:00
|
|
|
// connect button click handler
|
2024-09-28 00:32:15 +02:00
|
|
|
const QList<QAbstractButton*> aButtons = pButtonBox->buttons();
|
2024-10-04 14:49:12 +02:00
|
|
|
for (QAbstractButton* pButton : aButtons)
|
2024-09-28 00:32:15 +02:00
|
|
|
{
|
2024-10-04 12:50:10 +02:00
|
|
|
assert(pButton);
|
|
|
|
QObject::connect(pButton, &QAbstractButton::clicked, pDialog,
|
|
|
|
[pDialog, pButton] {
|
|
|
|
QtInstanceDialog::handleButtonClick(*pDialog, *pButton);
|
|
|
|
});
|
2024-09-28 00:32:15 +02:00
|
|
|
}
|
2024-09-28 00:26:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-09-25 09:48:09 +02:00
|
|
|
|
2024-10-04 22:56:05 +02:00
|
|
|
void QtBuilder::setMnemonicWidget(const OUString& rLabelId, const OUString& rMnemonicWidgetId)
|
2024-10-04 22:18:17 +02:00
|
|
|
{
|
2024-10-04 22:56:05 +02:00
|
|
|
QLabel* pLabel = get<QLabel>(rLabelId);
|
|
|
|
QObject* pBuddy = get_by_name(rMnemonicWidgetId);
|
|
|
|
|
|
|
|
if (!pLabel || !pBuddy || !pBuddy->isWidgetType())
|
|
|
|
return;
|
|
|
|
|
|
|
|
pLabel->setBuddy(static_cast<QWidget*>(pBuddy));
|
2024-10-04 22:18:17 +02:00
|
|
|
}
|
|
|
|
|
2024-09-25 09:48:09 +02:00
|
|
|
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");
|
|
|
|
}
|
2024-11-09 20:44:42 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2024-09-25 09:48:09 +02:00
|
|
|
|
2024-11-10 21:32:10 +01:00
|
|
|
QMenu* QtBuilder::createMenu(const OUString&)
|
|
|
|
{
|
|
|
|
assert(false && "Not implemented yet");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-11-10 22:03:28 +01:00
|
|
|
void QtBuilder::insertMenuObject(QMenu*, QMenu*, const OUString&, const OUString&, stringmap&,
|
|
|
|
stringmap&, accelmap&)
|
|
|
|
{
|
|
|
|
assert(false && "Not implemented yet");
|
|
|
|
}
|
|
|
|
|
2024-10-04 11:14:24 +02:00
|
|
|
void QtBuilder::applyAtkProperties(QObject* pObject, const stringmap& rProperties, bool)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-10-04 11:14:24 +02:00
|
|
|
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));
|
|
|
|
}
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
void QtBuilder::applyGridPackingProperties(QWidget* pCurrentChild, QGridLayout& rGrid,
|
2024-10-21 18:40:50 +02:00
|
|
|
const stringmap& rPackingProperties)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-10-25 21:32:56 +02:00
|
|
|
assert(pCurrentChild);
|
2024-10-28 09:48:15 +01:00
|
|
|
|
|
|
|
// 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;
|
2024-10-21 18:40:50 +02:00
|
|
|
|
2024-10-25 21:21:25 +02:00
|
|
|
const sal_Int32 nColumn = rPackingProperties.at(u"left-attach"_ustr).toInt32();
|
|
|
|
const sal_Int32 nRow = rPackingProperties.at(u"top-attach"_ustr).toInt32();
|
2024-10-21 18:40:50 +02:00
|
|
|
|
2024-10-25 22:53:14 +02:00
|
|
|
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();
|
|
|
|
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
rGrid.removeWidget(pCurrentChild);
|
|
|
|
rGrid.addWidget(pCurrentChild, nRow, nColumn, nRowSpan, nColumnSpan);
|
2024-10-21 18:40:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QtBuilder::applyPackingProperties(QObject* pCurrentChild, QObject* pParent,
|
|
|
|
const stringmap& rPackingProperties)
|
|
|
|
{
|
|
|
|
if (!pCurrentChild)
|
|
|
|
return;
|
|
|
|
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
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
|
2024-10-21 18:40:50 +02:00
|
|
|
if (QGridLayout* pGrid = qobject_cast<QGridLayout*>(pParent))
|
tdf#130857 qt weld: Add extra QWidget parents for layouts
For "GtkBox" and "GtkGrid" objects in .ui files,
don't just create the corresponding QLayout objects,
but create an extra QWidget object and set the
layout for that widget, i.e. use that QWidget as
the parent.
While this generally wouldn't be needed to properly
layout/handle things in Qt, having an associated
QWidget for the "GtkBox" and "GtkGrid" children
is needed in order to be able to create a
corresponding weld::Container (QtInstanceContainer)
for these, which derives from weld::Widget.
QLayout itself doesn't have the methods required to
implement weld::Widget, e.g. can't be hidden or shown.
Therefore, create a QWidget for these in addition,
except for special cases like the top-level layout
in a dialog or the dialog's button box.
For QGroupBox (created for "GtkFrame" objects),
this now means that the direct child is no more
necessarily a layout. Just setting a QWidget
as a child wouldn't suffice for proper layouting.
Therefore, explicitly create a layout for parent
widgets that don't have a layout set yet.
Adjust QtBuilder::applyPackingProperties
accordingly as well. Now, there's no more
use case to call QtBuilder::applyGridPackingProperties
with a QLayout for the current child. Get the
corresponding QWidget parent (if there is one)
before calling the method instead, and switch the
param from QObject* to QWidget* to simplify the
method.
Having an extra widget might have the side-effect
that extra spacing/margins might be used. If that
turns out to be a problem, these can presumably
explicitly be reduced (e.g. set to 0 for the relevant
objects) as needed later.
At least the 19 dialogs currently listed as supported in
QtInstanceBuilder::IsUIFileSupported still look OK to
me in a quick test with this commit in place.
Actually making use of the newly added widgets
to implement more of the QtInstanceContainer logic
will be done in separate commits.
Change-Id: I3d3600ddfc7883239177aafed57629c107cbdf5d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176033
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-11-04 19:06:15 +01:00
|
|
|
applyGridPackingProperties(pWidget, *pGrid, rPackingProperties);
|
2024-10-21 18:40:50 +02:00
|
|
|
else
|
|
|
|
SAL_WARN("vcl.qt", "QtBuilder::applyPackingProperties not yet implemented for this case");
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
|
2024-11-10 18:54:28 +01:00
|
|
|
void QtBuilder::applyTabChildProperties(QObject* pParent, const std::vector<OUString>& rIDs,
|
|
|
|
std::vector<vcl::EnumContext::Context>&,
|
|
|
|
stringmap& rProperties, stringmap&)
|
2024-11-09 21:23:04 +01:00
|
|
|
{
|
2024-11-10 18:54:28 +01:00
|
|
|
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));
|
2024-11-09 21:23:04 +01:00
|
|
|
}
|
|
|
|
|
2024-09-25 12:10:12 +02:00
|
|
|
void QtBuilder::set_response(std::u16string_view sID, short nResponse)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-09-25 12:10:12 +02:00
|
|
|
QPushButton* pPushButton = get<QPushButton>(sID);
|
|
|
|
assert(pPushButton);
|
|
|
|
pPushButton->setProperty(QtInstanceMessageDialog::PROPERTY_VCL_RESPONSE_CODE, int(nResponse));
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
|
2024-11-23 01:11:38 +01:00
|
|
|
void QtBuilder::deleteObject(QObject* pObject)
|
|
|
|
{
|
|
|
|
if (pObject->isWidgetType())
|
|
|
|
static_cast<QWidget*>(pObject)->hide();
|
|
|
|
pObject->deleteLater();
|
|
|
|
}
|
|
|
|
|
2024-09-27 21:52:18 +02:00
|
|
|
void QtBuilder::setProperties(QObject* pObject, stringmap& rProps)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-09-27 21:52:18 +02:00
|
|
|
if (QMessageBox* pMessageBox = qobject_cast<QMessageBox*>(pObject))
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-09-27 21:56:34 +02:00
|
|
|
for (auto const & [ rKey, rValue ] : rProps)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-25 13:21:55 +02:00
|
|
|
else if (qobject_cast<QCheckBox*>(pObject) || qobject_cast<QRadioButton*>(pObject))
|
2024-10-02 17:36:21 +02:00
|
|
|
{
|
2024-10-25 13:21:55 +02:00
|
|
|
QAbstractButton* pButton = static_cast<QAbstractButton*>(pObject);
|
2024-10-02 17:36:21 +02:00
|
|
|
for (auto const & [ rKey, rValue ] : rProps)
|
|
|
|
{
|
|
|
|
if (rKey == u"active")
|
2024-10-25 13:21:55 +02:00
|
|
|
pButton->setChecked(toBool(rValue));
|
2024-10-02 17:36:21 +02:00
|
|
|
else if (rKey == u"label")
|
2024-10-25 13:21:55 +02:00
|
|
|
pButton->setText(convertAccelerator(rValue));
|
2024-10-02 17:36:21 +02:00
|
|
|
}
|
|
|
|
}
|
2024-09-28 20:35:42 +02:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
2024-10-07 08:28:03 +02:00
|
|
|
else if (QPlainTextEdit* pTextEdit = qobject_cast<QPlainTextEdit*>(pObject))
|
|
|
|
{
|
|
|
|
for (auto const & [ rKey, rValue ] : rProps)
|
|
|
|
{
|
|
|
|
if (rKey == u"accepts-tab")
|
|
|
|
pTextEdit->setTabChangesFocus(!toBool(rValue));
|
|
|
|
}
|
|
|
|
}
|
2024-09-27 21:52:18 +02:00
|
|
|
else if (QPushButton* pButton = qobject_cast<QPushButton*>(pObject))
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
|
|
|
for (auto const & [ rKey, rValue ] : rProps)
|
|
|
|
{
|
2024-10-28 22:29:25 +01:00
|
|
|
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())
|
2024-11-23 01:11:38 +01:00
|
|
|
deleteObject(pImageLabel);
|
2024-10-28 22:29:25 +01:00
|
|
|
}
|
|
|
|
else if (rKey == u"label")
|
|
|
|
{
|
2024-09-25 09:48:09 +02:00
|
|
|
pButton->setText(convertAccelerator(rValue));
|
2024-10-28 22:29:25 +01:00
|
|
|
}
|
2024-09-25 09:48:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-08 22:19:59 +01:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-07 22:04:07 +01:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-25 09:48:09 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-09-27 23:00:46 +02:00
|
|
|
QDialogButtonBox* QtBuilder::findButtonBox(QDialog* pDialog)
|
2024-09-25 09:48:09 +02:00
|
|
|
{
|
2024-09-27 23:00:46 +02:00
|
|
|
assert(pDialog);
|
|
|
|
QLayout* pLayout = pDialog->layout();
|
|
|
|
if (!pLayout)
|
|
|
|
return nullptr;
|
|
|
|
|
2024-09-25 09:48:09 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-11-18 09:33:05 +01:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|