Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/vcl/builder.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#pragma once
11
12
#include <typeinfo>
13
#include <sal/log.hxx>
14
#include <vcl/dllapi.h>
15
#include <utility>
16
#include <vcl/menu.hxx>
17
#include <vcl/widgetbuilder.hxx>
18
#include <vcl/window.hxx>
19
#include <vcl/vclptr.hxx>
20
#include <vcl/toolboxid.hxx>
21
#include <vcl/wintypes.hxx>
22
#include <vcl/EnumContext.hxx>
23
#include <vcl/notebookbar/NotebookBarAddonsItem.hxx>
24
25
#include <memory>
26
#include <map>
27
#include <string_view>
28
#include <vector>
29
#ifdef check
30
#  //some problem with MacOSX and a check define
31
#  undef check
32
#endif
33
34
class ComboBox;
35
class FormattedField;
36
class ListBox;
37
class MessageDialog;
38
class NumericFormatter;
39
class ScrollBar;
40
class SvTabListBox;
41
class Slider;
42
class VclExpander;
43
class VclMultiLineEdit;
44
namespace com::sun::star::frame { class XFrame; }
45
46
/// Creates a hierarchy of vcl::Windows (widgets) from a .ui file for dialogs, sidebar, etc.
47
class VCL_DLLPUBLIC VclBuilder final : public WidgetBuilder<vcl::Window, VclPtr<vcl::Window>, PopupMenu, VclPtr<PopupMenu>>
48
{
49
public:
50
    /// These functions create a new widget with parent pParent and return it in rRet
51
    typedef void (*customMakeWidget)(VclPtr<vcl::Window> &rRet, const VclPtr<vcl::Window> &pParent, stringmap &rVec);
52
53
public:
54
    VclBuilder(vcl::Window* pParent, std::u16string_view sUIRootDir, const OUString& sUIFile,
55
               OUString sID = {},
56
               css::uno::Reference<css::frame::XFrame> xFrame
57
               = css::uno::Reference<css::frame::XFrame>(),
58
               bool bLegacy = true,
59
               std::unique_ptr<NotebookBarAddonsItem> pNotebookBarAddonsItem = nullptr);
60
    virtual ~VclBuilder();
61
    ///releases references and disposes all children.
62
    void disposeBuilder();
63
64
    //sID may not exist, but must be of type T if it does
65
    template <typename T = vcl::Window> T* get(std::u16string_view sID);
66
67
    vcl::Window*    get_widget_root();
68
69
    //release ownership of pWindow, i.e. don't delete it
70
    void            drop_ownership(const vcl::Window *pWindow);
71
72
    //see m_aDeferredProperties, you need this for toplevel dialogs
73
    //which build themselves from their ctor. The properties on
74
    //the top level are stored in m_aDeferredProperties and need
75
    //to be applied post ctor
76
    void            setDeferredProperties();
77
78
    static SymbolType mapStockToSymbol(std::u16string_view icon_name);
79
80
private:
81
    VclBuilder(const VclBuilder&) = delete;
82
    VclBuilder& operator=(const VclBuilder&) = delete;
83
84
    // owner for ListBox/ComboBox UserData
85
    std::vector<std::unique_ptr<OUString>> m_aUserData;
86
87
    //If the toplevel window has any properties which need to be set on it,
88
    //but the toplevel is the owner of the builder, then its ctor
89
    //has not been completed during the building, so properties for it
90
    //are collected here and need to be set afterwards, e.g. during
91
    //Show or Execute
92
    stringmap      m_aDeferredProperties;
93
94
    std::unique_ptr<NotebookBarAddonsItem> m_pNotebookBarAddonsItem;
95
96
    struct PackingData
97
    {
98
        bool m_bVerticalOrient;
99
        sal_Int32 m_nPosition;
100
        PackingData(bool bVerticalOrient = false)
101
0
            : m_bVerticalOrient(bVerticalOrient)
102
0
            , m_nPosition(-1)
103
0
        {
104
0
        }
105
    };
106
107
    struct WinAndId
108
    {
109
        OUString m_sID;
110
        VclPtr<vcl::Window> m_pWindow;
111
        PackingData m_aPackingData;
112
        WinAndId(OUString sId, vcl::Window *pWindow, bool bVertical)
113
0
            : m_sID(std::move(sId))
114
0
            , m_pWindow(pWindow)
115
0
            , m_aPackingData(bVertical)
116
0
        {
117
0
        }
118
    };
119
    std::vector<WinAndId> m_aChildren;
120
121
    struct ButtonImageWidgetMap
122
    {
123
        OUString m_sID;
124
        OUString m_sValue;
125
        bool m_bRadio;
126
        ButtonImageWidgetMap(OUString sId, OUString sValue, bool bRadio)
127
0
            : m_sID(std::move(sId))
128
0
            , m_sValue(std::move(sValue))
129
0
            , m_bRadio(bRadio)
130
0
        {
131
0
        }
132
    };
133
134
    typedef StringPair TextBufferMap;
135
    typedef StringPair WidgetAdjustmentMap;
136
    typedef StringPair ButtonMenuMap;
137
138
    void insertComboBoxOrListBoxItems(vcl::Window* pWindow,
139
                                      const std::vector<ComboBoxTextItem>& rItems,
140
                                      sal_Int32 nActiveIndex) override;
141
142
    static void     mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer);
143
144
    static void     mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment);
145
    static void     mungeAdjustment(FormattedField &rTarget, const Adjustment &rAdjustment);
146
    static void     mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment);
147
    static void     mungeAdjustment(Slider &rTarget, const Adjustment &rAdjustment);
148
149
    typedef std::map<OUString, int> ImageSizeMap;
150
151
152
153
    struct VclParserState
154
    {
155
        std::vector<TextBufferMap> m_aTextBufferMaps;
156
157
        std::vector<WidgetAdjustmentMap> m_aNumericFormatterAdjustmentMaps;
158
        std::vector<WidgetAdjustmentMap> m_aFormattedFormatterAdjustmentMaps;
159
        std::vector<WidgetAdjustmentMap> m_aScrollAdjustmentMaps;
160
        std::vector<WidgetAdjustmentMap> m_aSliderAdjustmentMaps;
161
162
        std::vector<ButtonImageWidgetMap> m_aButtonImageWidgetMaps;
163
        ImageSizeMap m_aImageSizeMap;
164
165
        std::vector<ButtonMenuMap> m_aButtonMenuMaps;
166
167
        std::map<VclPtr<vcl::Window>, VclPtr<vcl::Window>> m_aRedundantParentWidgets;
168
169
        std::map<VclPtr<vcl::Window>, stringmap> m_aAtkInfo;
170
171
        std::vector< VclPtr<VclExpander> > m_aExpanderWidgets;
172
173
        std::vector< VclPtr<MessageDialog> > m_aMessageDialogs;
174
175
        ToolBoxItemId m_nLastToolbarId;
176
177
        sal_uInt16 m_nLastMenuItemId;
178
179
        /* The renderer/column structure in .ui files for GtkTreeView is a set
180
           of compromise rules of expressing a layout in gtk terms which the
181
           vcl equivalent is also able to do.
182
183
           The GtkInstanceTreeView ctor has some more details of that.
184
185
           The ui files end up containing information as to what each TreeView
186
           is limited to, whether it will be used as a tree or a list and
187
           whether there are multiple columns or not, so here we extract enough
188
           of that information in the generic loader to determine what type of
189
           role this TreeView has.
190
        */
191
        sal_uInt16 m_nTreeViewRenderers;
192
        sal_uInt16 m_nTreeViewExpanders;
193
        sal_uInt16 m_nTreeViewColumnCount;
194
        bool m_bTreeViewSeenTextInColumn;
195
        bool m_bTreeHasHeader;
196
197
        VclParserState();
198
    };
199
200
    OUString    m_sID;
201
    VclPtr<vcl::Window> m_pParent;
202
    bool        m_bToplevelHasDeferredInit;
203
    bool        m_bToplevelHasDeferredProperties;
204
    bool        m_bToplevelParentFound;
205
    std::unique_ptr<VclParserState> m_pVclParserState;
206
207
    virtual void resetParserState() override;
208
    vcl::Window *get_by_name(std::u16string_view sID);
209
    void        delete_by_name(const OUString& sID);
210
211
    class sortIntoBestTabTraversalOrder
212
    {
213
    public:
214
                sortIntoBestTabTraversalOrder(VclBuilder *pBuilder)
215
0
                    : m_pBuilder(pBuilder) {}
216
217
        bool    operator()(const vcl::Window *pA, const vcl::Window *pB) const;
218
219
    private:
220
        VclBuilder *m_pBuilder;
221
    };
222
223
    /// XFrame to be able to extract labels and other properties of the UNO commands (like of .uno:Bold).
224
    css::uno::Reference<css::frame::XFrame> m_xFrame;
225
226
private:
227
    // tweak newly inserted child depending on window type
228
    void tweakInsertedChild(vcl::Window *pParent, vcl::Window* pCurrentChild,
229
                            std::string_view sType, std::string_view sInternalChild) override;
230
231
    VclPtr<vcl::Window> insertObject(vcl::Window* pParent, const OUString& rClass,
232
                                     std::string_view sType, const OUString& rID, stringmap& rProps,
233
                                     stringmap& rPangoAttributes, stringmap& rAtkProps) override;
234
235
    VclPtr<vcl::Window> makeObject(vcl::Window *pParent,
236
                    const OUString &rClass, const OUString &rID,
237
                    stringmap &rVec);
238
239
    void        connectNumericFormatterAdjustment(const OUString &id, const OUString &rAdjustment);
240
    void        connectFormattedFormatterAdjustment(const OUString &id, const OUString &rAdjustment);
241
242
    static int  getImageSize(const stringmap &rMap);
243
244
    void        extractBuffer(const OUString &id, stringmap &rVec);
245
    static bool extractAdjustmentToMap(const OUString &id, stringmap &rVec, std::vector<WidgetAdjustmentMap>& rAdjustmentMap);
246
    void        extractButtonImage(const OUString &id, stringmap &rMap, bool bRadio);
247
248
    void applyPackingProperties(vcl::Window* pCurrent, vcl::Window* pParent,
249
                                const stringmap& rPackingProperties) override;
250
    virtual void applyTabChildProperties(vcl::Window* pParent, const std::vector<OUString>& rIDs,
251
                                         std::vector<vcl::EnumContext::Context>& rContext, stringmap& rProperties,
252
                                         stringmap& rAtkProperties) override;
253
254
    void insertMenuObject(PopupMenu* pParent, PopupMenu* pSubMenu, const OUString& rClass,
255
                          const OUString& rID, stringmap& rProps, stringmap& rAtkProps,
256
                          accelmap& rAccels) override;
257
258
    // if bToolbarItem=true, pParent is the ToolBox that the item belongs to, since there's no widget for the item itself
259
    void applyAtkProperties(vcl::Window* pWindow, const stringmap& rProperties,
260
                            bool bToolbarItem) override;
261
262
    void setMnemonicWidget(const OUString& rLabelId, const OUString& rMnemonicWidgetId) override;
263
    void setRadioButtonGroup(const OUString& rRadioButtonId, const OUString& rRadioGroupId) override;
264
    void setPriority(vcl::Window* pWindow, int nPriority) override;
265
    void setContext(vcl::Window* pWindow,
266
                    std::vector<vcl::EnumContext::Context>&& aContext) override;
267
268
    virtual bool isHorizontalTabControl(vcl::Window* pWindow) override;
269
270
    virtual VclPtr<PopupMenu> createMenu(const OUString& rID) override;
271
272
    PackingData get_window_packing_data(const vcl::Window *pWindow) const;
273
    void        set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition);
274
275
    static vcl::Window* prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle);
276
    void        cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap);
277
278
    void set_response(const OUString& rId, int nResponse) override;
279
280
    OUString        get_by_window(const vcl::Window *pWindow) const;
281
    void            delete_by_window(vcl::Window *pWindow);
282
};
283
284
namespace BuilderUtils
285
{
286
    //apply the properties of rProps to pWindow
287
    void set_properties(vcl::Window *pWindow, const VclBuilder::stringmap &rProps);
288
289
    //Convert _ gtk markup to ~ vcl markup
290
    OUString convertMnemonicMarkup(std::u16string_view rIn);
291
292
    OUString extractCustomProperty(VclBuilder::stringmap &rMap);
293
294
    bool extractDropdown(VclBuilder::stringmap &rMap);
295
296
    //add a default value of 25 width-chars to a map if width-chars not set
297
    void ensureDefaultWidthChars(VclBuilder::stringmap &rMap);
298
299
    //Helpers to retrofit all the existing code to the builder
300
    void reorderWithinParent(std::vector< vcl::Window*>& rChilds, bool bIsButtonBox);
301
    void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition);
302
303
    //Convert an accessibility role name to accessibility role number
304
    sal_Int16 getRoleFromName(std::u16string_view roleName);
305
}
306
307
//sID may not exist, but must be of type T if it does
308
template <typename T>
309
inline T* VclBuilder::get(std::u16string_view sID)
310
0
{
311
0
    vcl::Window *w = get_by_name(sID);
312
0
    SAL_WARN_IF(w && !dynamic_cast<T*>(w), "vcl.layout",
313
0
                ".ui widget \"" << OUStringToOString(sID, RTL_TEXTENCODING_UTF8)
314
0
                                << "\" needs to correspond to vcl type " << typeid(T).name());
315
0
    assert(!w || dynamic_cast<T*>(w));
316
0
    return static_cast<T*>(w);
317
0
}
Unexecuted instantiation: vcl::Window* VclBuilder::get<vcl::Window>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: MessageDialog* VclBuilder::get<MessageDialog>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Dialog* VclBuilder::get<Dialog>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: vcl::RoadmapWizard* VclBuilder::get<vcl::RoadmapWizard>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclBox* VclBuilder::get<VclBox>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclGrid* VclBuilder::get<VclGrid>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclPaned* VclBuilder::get<VclPaned>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclFrame* VclBuilder::get<VclFrame>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclScrolledWindow* VclBuilder::get<VclScrolledWindow>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Button* VclBuilder::get<Button>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: MenuButton* VclBuilder::get<MenuButton>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: FixedHyperlink* VclBuilder::get<FixedHyperlink>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: PushButton* VclBuilder::get<PushButton>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: RadioButton* VclBuilder::get<RadioButton>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: CheckBox* VclBuilder::get<CheckBox>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Slider* VclBuilder::get<Slider>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: ProgressBar* VclBuilder::get<ProgressBar>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Throbber* VclBuilder::get<Throbber>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: FixedImage* VclBuilder::get<FixedImage>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Calendar* VclBuilder::get<Calendar>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Edit* VclBuilder::get<Edit>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: FormattedField* VclBuilder::get<FormattedField>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: SvTabListBox* VclBuilder::get<SvTabListBox>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: IconView* VclBuilder::get<IconView>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: Control* VclBuilder::get<Control>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclMultiLineEdit* VclBuilder::get<VclMultiLineEdit>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclExpander* VclBuilder::get<VclExpander>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclDrawingArea* VclBuilder::get<VclDrawingArea>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: DockingWindow* VclBuilder::get<DockingWindow>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: ToolBox* VclBuilder::get<ToolBox>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: ScrollBar* VclBuilder::get<ScrollBar>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: FixedText* VclBuilder::get<FixedText>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Unexecuted instantiation: VclHBox* VclBuilder::get<VclHBox>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
318
319
/*
320
 * @return true if rValue is "True", "true", "1", etc.
321
 */
322
VCL_DLLPUBLIC bool toBool(std::u16string_view rValue);
323
324
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */