Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/include/vcl/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 18 kB image not shown  

Quelle  widgetbuilder.hxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * 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/.
 */


#pragma once

#include <com/sun/star/uno/Exception.hpp>
#include <comphelper/diagnose_ex.hxx>
#include <sal/log.hxx>
#include <vcl/builderbase.hxx>
#include <xmlreader/span.hxx>
#include <xmlreader/xmlreader.hxx>

/* Template class for a Builder to create a hierarchy of widgets from a .ui file
 * for dialogs, sidebar, etc.
 *
 * This class parses the .ui file and calls overridable methods
 * so subclasses can create the widgets of a specific toolkit.
 *
 * The VclBuilder subclass is the implementation using LibreOffice's own VCL toolkit
 * and the QtBuilder subclass uses native Qt widgets.
 */

template <typename Widget, typename WidgetPtr, typename MenuClass, typename MenuPtr>
class WidgetBuilder : public BuilderBase
{
protected:
    struct MenuAndId
    {
        OUString m_sID;
        MenuPtr m_pMenu;
        MenuAndId(OUString sId, MenuClass* pMenu)
            : m_sID(std::move(sId))
            , m_pMenu(pMenu)
        {
        }
    };

    WidgetBuilder(std::u16string_view sUIDir, const OUString& rUIFile, bool bLegacy)
        : BuilderBase(sUIDir, rUIFile, bLegacy)
    {
    }
    virtual ~WidgetBuilder() = default;

    std::vector<MenuAndId> m_aMenus;

public:
    //sID may not exist
    MenuClass* get_menu(std::u16string_view sID)
    {
        for (auto const& menu : m_aMenus)
        {
            if (menu.m_sID == sID)
                return menu.m_pMenu;
        }

        return nullptr;
    }

protected:
    void processUIFile(Widget* pParent)
    {
        try
        {
            xmlreader::XmlReader reader(getUIFileUrl());
            handleChild(pParent, nullptr, reader);
        }
        catch (const css::uno::Exception& rExcept)
        {
            TOOLS_WARN_EXCEPTION("vcl.builder""Unable to read .ui file " << getUIFileUrl());
            reportException(rExcept);
            assert(false && "missing ui file or missing gb_CppunitTest_use_uiconfigs dependency");
            throw;
        }

        // Set Mnemonic widgets when everything has been imported
        for (const MnemonicWidgetMap& rMnemonic : getMnemonicWidgetMaps())
        {
            setMnemonicWidget(rMnemonic.m_sID, rMnemonic.m_sValue);
        }

        // Set radiobutton groups when everything has been imported
        for (const RadioButtonGroupMap& rGroup : getRadioButtonGroupMaps())
            setRadioButtonGroup(rGroup.m_sID, rGroup.m_sValue);
    }

    // either pParent or pAtkProps must be set, pParent for a child of a widget, pAtkProps for
    // collecting the atk info for a GtkMenuItem or tab child
    void handleChild(Widget* pParent, stringmap* pAtkProps, xmlreader::XmlReader& reader,
                     bool bToolbarItem = false)
    {
        xmlreader::Span name;
        int nsId;
        OString sType, sInternalChild;

        while (reader.nextAttribute(&nsId, &name))
        {
            if (name == "type")
            {
                name = reader.getAttributeValue(false);
                sType = OString(name.begin, name.length);
            }
            else if (name == "internal-child")
            {
                name = reader.getAttributeValue(false);
                sInternalChild = OString(name.begin, name.length);
            }
        }

        if (sType == "tab")
        {
            handleTabChild(pParent, reader);
            return;
        }

        WidgetPtr pCurrentChild = nullptr;
        int nLevel = 1;
        while (true)
        {
            xmlreader::XmlReader::Result res
                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);

            if (res == xmlreader::XmlReader::Result::Begin)
            {
                if (name == "object" || name == "placeholder")
                {
                    pCurrentChild = handleObject(pParent, pAtkProps, reader, sType, sInternalChild,
                                                 bToolbarItem);

                    bool bObjectInserted = pCurrentChild && pParent != pCurrentChild;
                    if (bObjectInserted)
                        tweakInsertedChild(pParent, pCurrentChild, sType, sInternalChild);
                }
                else if (name == "packing")
                {
                    const stringmap aPackingProperties = collectPackingProperties(reader);
                    applyPackingProperties(pCurrentChild, pParent, aPackingProperties);
                }
                else if (name == "interface")
                {
                    while (reader.nextAttribute(&nsId, &name))
                    {
                        if (name == "domain")
                            handleInterfaceDomain(reader);
                    }
                    ++nLevel;
                }
                else
                    ++nLevel;
            }

            if (res == xmlreader::XmlReader::Result::End)
                --nLevel;

            if (!nLevel)
                break;

            if (res == xmlreader::XmlReader::Result::Done)
                break;
        }
    }

    WidgetPtr handleObject(Widget* pParent, stringmap* pAtkProps, xmlreader::XmlReader&&nbsp;reader,
                           std::string_view sType, std::string_view sInternalChild,
                           bool bToolbarItem)
    {
        OUString sClass;
        OUString sID;
        OUString sCustomProperty;
        extractClassAndIdAndCustomProperty(reader, sClass, sID, sCustomProperty);

        if (sClass == "GtkListStore" || sClass == "GtkTreeStore")
        {
            handleListStore(reader, sID, sClass);
            return nullptr;
        }
        else if (sClass == "GtkMenu")
        {
            handleMenu(reader, sID);
            return nullptr;
        }
        else if (sClass == "GtkSizeGroup")
        {
            handleSizeGroup(reader);
            return nullptr;
        }
        else if (sClass == "AtkObject")
        {
            assert((pParent || pAtkProps) && "must have one set");
            assert(!(pParent && pAtkProps) && "must not have both");
            auto aAtkProperties = handleAtkObject(reader);
            if (pParent)
                applyAtkProperties(pParent, aAtkProperties, bToolbarItem);
            if (pAtkProps)
                *pAtkProps = std::move(aAtkProperties);
            return nullptr;
        }

        int nLevel = 1;

        stringmap aProperties, aPangoAttributes;
        stringmap aAtkAttributes;
        std::vector<ComboBoxTextItem> aItems;

        if (!sCustomProperty.isEmpty())
            aProperties[u"customproperty"_ustr] = sCustomProperty;

        // Internal-children default in glade to not having their visible bits set
        // even though they are visible (generally anyway)
        if (!sInternalChild.empty())
            aProperties[u"visible"_ustr] = "True";

        WidgetPtr pCurrentChild = nullptr;
        while (true)
        {
            xmlreader::Span name;
            int nsId;
            xmlreader::XmlReader::Result res
                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);

            if (res == xmlreader::XmlReader::Result::Done)
                break;

            if (res == xmlreader::XmlReader::Result::Begin)
            {
                if (name == "child")
                {
                    if (!pCurrentChild)
                    {
                        pCurrentChild = insertObject(pParent, sClass, sType, sID, aProperties,
                                                     aPangoAttributes, aAtkAttributes);
                    }
                    handleChild(pCurrentChild, nullptr, reader, isToolbarItemClass(sClass));
                }
                else if (name == "items")
                    aItems = handleItems(reader);
                else if (name == "style")
                {
                    int nPriority = 0;
                    std::vector<vcl::EnumContext::Context> aContext
                        = handleStyle(reader, nPriority);
                    if (nPriority != 0)
                        setPriority(pCurrentChild, nPriority);
                    if (!aContext.empty())
                        setContext(pCurrentChild, std::move(aContext));
                }
                else
                {
                    ++nLevel;
                    if (name == "property")
                        collectProperty(reader, aProperties);
                    else if (name == "attribute")
                        collectPangoAttribute(reader, aPangoAttributes);
                    else if (name == "relation")
                        collectAtkRelationAttribute(reader, aAtkAttributes);
                    else if (name == "role")
                        collectAtkRoleAttribute(reader, aAtkAttributes);
                    else if (name == "action-widget")
                        handleActionWidget(reader);
                }
            }

            if (res == xmlreader::XmlReader::Result::End)
            {
                --nLevel;
            }

            if (!nLevel)
                break;
        }

        if (sClass == "GtkAdjustment")
        {
            addAdjustment(sID, aProperties);
            return nullptr;
        }
        else if (sClass == "GtkTextBuffer")
        {
            addTextBuffer(sID, aProperties);
            return nullptr;
        }

        if (!pCurrentChild)
        {
            pCurrentChild = insertObject(pParent, sClass, sType, sID, aProperties, aPangoAttributes,
                                         aAtkAttributes);
        }

        if (!aItems.empty())
            insertComboBoxOrListBoxItems(pCurrentChild, aProperties, aItems);

        return pCurrentChild;
    }

    void handleTabChild(Widget* pParent, xmlreader::XmlReader& reader)
    {
        std::vector<OUString> sIDs;

        int nLevel = 1;
        stringmap aProperties;
        stringmap aAtkProperties;
        std::vector<vcl::EnumContext::Context> context;

        while (true)
        {
            xmlreader::Span name;
            int nsId;

            xmlreader::XmlReader::Result res
                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);

            if (res == xmlreader::XmlReader::Result::Begin)
            {
                ++nLevel;
                if (name == "object")
                {
                    while (reader.nextAttribute(&nsId, &name))
                    {
                        if (name == "id")
                        {
                            name = reader.getAttributeValue(false);
                            OUString sID(name.begin, name.length, RTL_TEXTENCODING_UTF8);
                            sal_Int32 nDelim = sID.indexOf(':');
                            if (nDelim != -1)
                            {
                                aProperties[u"customproperty"_ustr] = sID.copy(nDelim + 1);
                                sID = sID.copy(0, nDelim);
                            }
                            sIDs.push_back(sID);
                        }
                    }
                }
                else if (name == "style")
                {
                    int nPriority = 0;
                    context = handleStyle(reader, nPriority);
                    --nLevel;
                }
                else if (name == "property")
                    collectProperty(reader, aProperties);
                else if (name == "child" && isHorizontalTabControl(pParent))
                {
                    // just to collect the atk properties (if any) for the label
                    handleChild(nullptr, &aAtkProperties, reader);
                    --nLevel;
                }
            }

            if (res == xmlreader::XmlReader::Result::End)
                --nLevel;

            if (!nLevel)
                break;

            if (res == xmlreader::XmlReader::Result::Done)
                break;
        }

        if (!pParent)
            return;

        applyTabChildProperties(pParent, sIDs, context, aProperties, aAtkProperties);
    }

    void handleMenu(xmlreader::XmlReader& reader, const OUString& rID)
    {
        MenuPtr pCurrentMenu = createMenu(rID);

        int nLevel = 1;

        stringmap aProperties;

        while (true)
        {
            xmlreader::Span name;
            int nsId;

            xmlreader::XmlReader::Result res
                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);

            if (res == xmlreader::XmlReader::Result::Done)
                break;

            if (res == xmlreader::XmlReader::Result::Begin)
            {
                if (name == "child")
                {
                    handleMenuChild(pCurrentMenu, reader);
                }
                else
                {
                    ++nLevel;
                    if (name == "property")
                        collectProperty(reader, aProperties);
                }
            }

            if (res == xmlreader::XmlReader::Result::End)
            {
                --nLevel;
            }

            if (!nLevel)
                break;
        }

        m_aMenus.emplace_back(rID, pCurrentMenu);
    }

    void handleMenuChild(MenuClass* pParent, xmlreader::XmlReader& reader)
    {
        xmlreader::Span name;
        int nsId;

        int nLevel = 1;
        while (true)
        {
            xmlreader::XmlReader::Result res
                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);

            if (res == xmlreader::XmlReader::Result::Begin)
            {
                if (name == "object" || name == "placeholder")
                {
                    handleMenuObject(pParent, reader);
                }
                else
                    ++nLevel;
            }

            if (res == xmlreader::XmlReader::Result::End)
                --nLevel;

            if (!nLevel)
                break;

            if (res == xmlreader::XmlReader::Result::Done)
                break;
        }
    }

    void handleMenuObject(MenuClass* pParent, xmlreader::XmlReader& reader)
    {
        OUString sClass;
        OUString sID;
        OUString sCustomProperty;
        MenuClass* pSubMenu = nullptr;

        xmlreader::Span name;
        int nsId;

        while (reader.nextAttribute(&nsId, &name))
        {
            if (name == "class")
            {
                name = reader.getAttributeValue(false);
                sClass = OUString(name.begin, name.length, RTL_TEXTENCODING_UTF8);
            }
            else if (name == "id")
            {
                name = reader.getAttributeValue(false);
                sID = OUString(name.begin, name.length, RTL_TEXTENCODING_UTF8);
                if (isLegacy())
                {
                    sal_Int32 nDelim = sID.indexOf(':');
                    if (nDelim != -1)
                    {
                        sCustomProperty = sID.subView(nDelim + 1);
                        sID = sID.copy(0, nDelim);
                    }
                }
            }
        }

        int nLevel = 1;

        stringmap aProperties;
        stringmap aAtkProperties;
        accelmap aAccelerators;

        if (!sCustomProperty.isEmpty())
            aProperties[u"customproperty"_ustr] = sCustomProperty;

        while (true)
        {
            xmlreader::XmlReader::Result res
                = reader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);

            if (res == xmlreader::XmlReader::Result::Done)
                break;

            if (res == xmlreader::XmlReader::Result::Begin)
            {
                if (name == "child")
                {
                    size_t nChildMenuIdx = m_aMenus.size();
                    handleChild(nullptr, &aAtkProperties, reader);
                    bool bSubMenuInserted = m_aMenus.size() > nChildMenuIdx;
                    if (bSubMenuInserted)
                        pSubMenu = m_aMenus[nChildMenuIdx].m_pMenu;
                }
                else
                {
                    ++nLevel;
                    if (name == "property")
                        collectProperty(reader, aProperties);
                    else if (name == "accelerator")
                        collectAccelerator(reader, aAccelerators);
                }
            }

            if (res == xmlreader::XmlReader::Result::End)
            {
                --nLevel;
            }

            if (!nLevel)
                break;
        }

        insertMenuObject(pParent, pSubMenu, sClass, sID, aProperties, aAtkProperties,
                         aAccelerators);
    }

    virtual void applyAtkProperties(Widget* pWidget, const stringmap& rProperties,
                                    bool bToolbarItem)
        = 0;
    virtual void applyPackingProperties(Widget* pCurrentChild, Widget* pParent,
                                        const stringmap& rPackingProperties)
        = 0;
    virtual void applyTabChildProperties(Widget* pParent, const std::vector<OUString>& rIDs,
                                         std::vector<vcl::EnumContext::Context>& rContext,
                                         stringmap& rProperties, stringmap& rAtkProperties)
        = 0;
    virtual void insertComboBoxOrListBoxItems(Widget* pWidget, stringmap& rMap,
                                              const std::vector<ComboBoxTextItem>& rItems)
        = 0;

    virtual WidgetPtr insertObject(Widget* pParent, const OUString& rClass, std::string_view sType,
                                   const OUString& rID, stringmap& rProps,
                                   stringmap& rPangoAttributes, stringmap& rAtkProps)
        = 0;

    virtual void tweakInsertedChild(Widget* pParent, Widget* pCurrentChild, std::string_view sType,
                                    std::string_view sInternalChild)
        = 0;

    virtual void setMnemonicWidget(const OUString& rLabelId, const OUString& rMnemonicWidgetId) = 0;
    virtual void setRadioButtonGroup(const OUString& rRadioButtonId, const OUString&&nbsp;rRadioGroupId)
        = 0;
    virtual void setPriority(Widget* pWidget, int nPriority) = 0;
    virtual void setContext(Widget* pWidget, std::vector<vcl::EnumContext::Context>&& aContext) = 0;

    // Whether the given widget is a horizontal, i.e. non-vertical tab control
    virtual bool isHorizontalTabControl(Widget* pWidget) = 0;

    virtual MenuPtr createMenu(const OUString& rID) = 0;
    virtual void insertMenuObject(MenuClass* pParent, MenuClass* pSubMenu, const OUString&&nbsp;rClass,
                                  const OUString& rID, stringmap& rProps, stringmap& rAtkProps,
                                  accelmap& rAccels)
        = 0;
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=98 H=86 G=91

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.