Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/framework/source/uielement/toolbarmerger.cxx
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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
22
#include <string_view>
23
24
#include <uielement/toolbarmerger.hxx>
25
#include <framework/generictoolbarcontroller.hxx>
26
27
#include <uielement/buttontoolbarcontroller.hxx>
28
#include <uielement/comboboxtoolbarcontroller.hxx>
29
#include <uielement/dropdownboxtoolbarcontroller.hxx>
30
#include <uielement/edittoolbarcontroller.hxx>
31
#include <uielement/imagebuttontoolbarcontroller.hxx>
32
#include <uielement/spinfieldtoolbarcontroller.hxx>
33
#include <uielement/togglebuttontoolbarcontroller.hxx>
34
#include <uielement/FixedTextToolbarController.hxx>
35
#include <uielement/FixedImageToolbarController.hxx>
36
#include <o3tl/string_view.hxx>
37
38
namespace framework
39
{
40
41
const char MERGE_TOOLBAR_URL[]             = "URL";
42
const char MERGE_TOOLBAR_TITLE[]           = "Title";
43
const char MERGE_TOOLBAR_CONTEXT[]         = "Context";
44
const char MERGE_TOOLBAR_TARGET[]          = "Target";
45
const char MERGE_TOOLBAR_CONTROLTYPE[]     = "ControlType";
46
const char MERGE_TOOLBAR_WIDTH[]           = "Width";
47
48
const char16_t MERGECOMMAND_ADDAFTER[]     = u"AddAfter";
49
const char16_t MERGECOMMAND_ADDBEFORE[]    = u"AddBefore";
50
const char16_t MERGECOMMAND_REPLACE[]      = u"Replace";
51
const char16_t MERGECOMMAND_REMOVE[]       = u"Remove";
52
53
const char16_t MERGEFALLBACK_ADDLAST[]     = u"AddLast";
54
const char16_t MERGEFALLBACK_ADDFIRST[]    = u"AddFirst";
55
const char16_t MERGEFALLBACK_IGNORE[]      = u"Ignore";
56
57
const char16_t TOOLBARCONTROLLER_BUTTON[]  = u"Button";
58
const char16_t TOOLBARCONTROLLER_COMBOBOX[] = u"Combobox";
59
const char16_t TOOLBARCONTROLLER_EDIT[]    = u"Editfield";
60
const char16_t TOOLBARCONTROLLER_SPINFIELD[] = u"Spinfield";
61
const char16_t TOOLBARCONTROLLER_IMGBUTTON[] = u"ImageButton";
62
const char16_t TOOLBARCONTROLLER_DROPDOWNBOX[] = u"Dropdownbox";
63
const char16_t TOOLBARCONTROLLER_DROPDOWNBTN[] = u"DropdownButton";
64
const char16_t TOOLBARCONTROLLER_TOGGLEDDBTN[] = u"ToggleDropdownButton";
65
const char16_t TOOLBARCONTROLLER_FIXEDIMAGE[] = u"FixedImage";
66
const char16_t TOOLBARCONTROLLER_FIXEDTEXT[] = u"FixedText";
67
68
const char   TOOLBOXITEM_SEPARATOR_STR[]   = "private:separator";
69
70
using namespace ::com::sun::star;
71
72
/**
73
 Check whether a module identifier is part of a context
74
 defined by a colon separated list of module identifier.
75
76
 @param
77
     rContext
78
79
     Describes a context string list where all contexts
80
     are delimited by a colon. For more information about
81
     the module identifier used as context strings see the
82
     IDL description of css::frame::XModuleManager
83
84
 @param
85
     rModuleIdentifier
86
87
     A string describing a module identifier. See IDL
88
     description of css::frame::XModuleManager.
89
90
 @result
91
     The result is true if the rContext is an empty string
92
     or rModuleIdentifier is part of the context string.
93
94
*/
95
bool ToolBarMerger::IsCorrectContext(
96
    std::u16string_view rContext,
97
    std::u16string_view rModuleIdentifier )
98
0
{
99
0
    return ( rContext.empty() || ( rContext.find( rModuleIdentifier ) != std::u16string_view::npos ));
100
0
}
101
102
/**
103
 Converts a sequence, sequence of property values to
104
 a vector of structs.
105
106
 @param
107
     rSequence
108
109
     Provides a sequence, sequence of property values.
110
111
 @param
112
     rContainer
113
114
     A vector of AddonToolbarItems which will hold the
115
     conversion from the rSequence argument.
116
*/
117
void ToolBarMerger::ConvertSeqSeqToVector(
118
    const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSequence,
119
    AddonToolbarItemContainer& rContainer )
120
0
{
121
0
    sal_Int32 nLen( rSequence.getLength() );
122
0
    for ( sal_Int32 i = 0; i < nLen; i++ )
123
0
    {
124
0
        AddonToolbarItem aAddonToolbarItem;
125
0
        ConvertSequenceToValues( rSequence[i],
126
0
                                 aAddonToolbarItem.aCommandURL,
127
0
                                 aAddonToolbarItem.aLabel,
128
0
                                 aAddonToolbarItem.aTarget,
129
0
                                 aAddonToolbarItem.aContext,
130
0
                                 aAddonToolbarItem.aControlType,
131
0
                                 aAddonToolbarItem.nWidth );
132
0
        rContainer.push_back( aAddonToolbarItem );
133
0
    }
134
0
}
135
136
/**
137
 Converts a sequence of property values to single
138
 values.
139
140
 @param
141
     rSequence
142
143
     Provides a sequence of property values.
144
145
 @param
146
     rCommandURL
147
148
     Contains the value of the property with
149
     Name="CommandURL".
150
151
 @param
152
     rLabel
153
154
     Contains the value of the property with
155
     Name="Title"
156
157
 @param
158
     rTarget
159
160
     Contains the value of the property with
161
     Name="Target"
162
163
 @param
164
     rContext
165
166
     Contains the value of the property with
167
     Name="Context"
168
169
 @param
170
     rControlType
171
172
     Contains the value of the property with
173
     Name="ControlType"
174
175
 @result
176
     All possible mapping between sequence of property
177
     values and the single values are done.
178
179
*/
180
void ToolBarMerger::ConvertSequenceToValues(
181
    const uno::Sequence< beans::PropertyValue >& rSequence,
182
    OUString& rCommandURL,
183
    OUString& rLabel,
184
    OUString& rTarget,
185
    OUString& rContext,
186
    OUString& rControlType,
187
    sal_uInt16& rWidth )
188
0
{
189
0
    for ( beans::PropertyValue const & prop : rSequence )
190
0
    {
191
0
        if ( prop.Name == MERGE_TOOLBAR_URL )
192
0
            prop.Value >>= rCommandURL;
193
0
        else if ( prop.Name == MERGE_TOOLBAR_TITLE )
194
0
            prop.Value >>= rLabel;
195
0
        else if ( prop.Name == MERGE_TOOLBAR_CONTEXT )
196
0
            prop.Value >>= rContext;
197
0
        else if ( prop.Name == MERGE_TOOLBAR_TARGET )
198
0
            prop.Value >>= rTarget;
199
0
        else if ( prop.Name == MERGE_TOOLBAR_CONTROLTYPE )
200
0
            prop.Value >>= rControlType;
201
0
        else if ( prop.Name == MERGE_TOOLBAR_WIDTH )
202
0
        {
203
0
            sal_Int32 aValue = 0;
204
0
            prop.Value >>= aValue;
205
0
            rWidth = sal_uInt16( aValue );
206
0
        }
207
0
    }
208
0
}
209
210
/**
211
 Tries to find the reference point provided and delivers
212
 position and result of the search process.
213
214
 @param
215
     pToolbar
216
217
     Must be a valid pointer to a toolbar with items which
218
     should be searched.
219
@param
220
     nFirstItem
221
222
     First toolbar item to search from.
223
224
 @param
225
     rReferencePoint
226
227
     A command URL which should be the reference point for
228
     the coming merge operation.
229
230
 @result
231
     Provides information about the search result, the
232
     position of the reference point and the toolbar used.
233
*/
234
ReferenceToolbarPathInfo ToolBarMerger::FindReferencePoint(
235
    const ToolBox* pToolbar, sal_uInt16 nFirstItem,
236
    std::u16string_view rReferencePoint )
237
0
{
238
0
    ReferenceToolbarPathInfo aResult;
239
0
    aResult.bResult  = false;
240
0
    aResult.nPos     = ToolBox::ITEM_NOTFOUND;
241
242
0
    const ToolBox::ImplToolItems::size_type nSize( pToolbar->GetItemCount() );
243
244
0
    for ( ToolBox::ImplToolItems::size_type i = nFirstItem; i < nSize; i++ )
245
0
    {
246
0
        const ToolBoxItemId nItemId = pToolbar->GetItemId( i );
247
0
        if ( nItemId > ToolBoxItemId(0) )
248
0
        {
249
0
            const OUString rCmd = pToolbar->GetItemCommand( nItemId );
250
0
            if ( rCmd == rReferencePoint )
251
0
            {
252
0
                aResult.bResult = true;
253
0
                aResult.nPos    = i;
254
0
                return aResult;
255
0
            }
256
0
        }
257
0
    }
258
259
0
    return aResult;
260
0
}
261
262
/**
263
 Processes a merge operation.
264
265
 @param
266
     pToolbar
267
268
     A valid pointer to the toolbar where the merge
269
     operation is applied to.
270
271
 @param
272
     nPos
273
274
     The reference position of the toolbar item for
275
     the merge operation. Value must be between
276
     0 and number of toolbar items - 1.
277
278
 @param
279
     rItemId
280
281
     A unique item ID.
282
283
 @param
284
     rModuleIdentifier
285
286
     The current application module context.
287
288
 @param
289
     rMergeCommand
290
291
     A merge command.
292
293
 @param
294
     rMergeCommandParameter.
295
296
     An optional argument for the merge command.
297
298
 @param
299
     rItems
300
301
     Toolbar items which are associated to the merge
302
     command.
303
304
 @result
305
     Returns true for a successful operation otherwise
306
     false.
307
*/
308
bool ToolBarMerger::ProcessMergeOperation(
309
    ToolBox*                               pToolbar,
310
    ToolBox::ImplToolItems::size_type      nPos,
311
    ToolBoxItemId&                         rItemId,
312
    CommandToInfoMap&                      rCommandMap,
313
    std::u16string_view                    rModuleIdentifier,
314
    std::u16string_view                    rMergeCommand,
315
    std::u16string_view                    rMergeCommandParameter,
316
    const AddonToolbarItemContainer&       rItems )
317
0
{
318
0
    if ( rMergeCommand == MERGECOMMAND_ADDAFTER )
319
0
        MergeItems( pToolbar, nPos, 1, rItemId, rCommandMap, rModuleIdentifier, rItems );
320
0
    else if ( rMergeCommand == MERGECOMMAND_ADDBEFORE )
321
0
        MergeItems( pToolbar, nPos, 0, rItemId, rCommandMap, rModuleIdentifier, rItems );
322
0
    else if ( rMergeCommand == MERGECOMMAND_REPLACE )
323
0
        ReplaceItem( pToolbar, nPos, rItemId, rCommandMap, rModuleIdentifier, rItems );
324
0
    else if ( rMergeCommand == MERGECOMMAND_REMOVE )
325
0
        RemoveItems( pToolbar, nPos, rMergeCommandParameter );
326
0
    else
327
0
        return false;
328
0
    return true;
329
0
}
330
331
/**
332
 Processes a merge fallback operation.
333
334
 @param
335
     pToolbar
336
337
     A valid pointer to the toolbar where the merge
338
     fall back operation is applied to.
339
340
 @param
341
     nPos
342
343
     The reference position of the toolbar item for
344
     the merge operation. Value must be between
345
     0 and number of toolbar items - 1.
346
347
 @param
348
     rItemId
349
350
     A unique item ID.
351
352
 @param
353
     rModuleIdentifier
354
355
     The current application module context.
356
357
 @param
358
     rMergeCommand
359
360
     A merge command.
361
362
 @param
363
     rItems
364
365
     Toolbar items which are associated to the merge
366
     command.
367
368
 @result
369
     Returns true for a successful operation otherwise
370
     false.
371
*/
372
bool ToolBarMerger::ProcessMergeFallback(
373
    ToolBox*                         pToolbar,
374
    ToolBoxItemId&                   rItemId,
375
    CommandToInfoMap&                rCommandMap,
376
    std::u16string_view       rModuleIdentifier,
377
    std::u16string_view       rMergeCommand,
378
    std::u16string_view       rMergeFallback,
379
    const AddonToolbarItemContainer& rItems )
380
0
{
381
0
    if (( rMergeFallback == MERGEFALLBACK_IGNORE ) ||
382
0
        ( rMergeCommand == MERGECOMMAND_REPLACE ) ||
383
0
        ( rMergeCommand == MERGECOMMAND_REMOVE ) )
384
0
    {
385
0
        return true;
386
0
    }
387
0
    else if (( rMergeCommand == MERGECOMMAND_ADDBEFORE ) ||
388
0
             ( rMergeCommand == MERGECOMMAND_ADDAFTER ) )
389
0
    {
390
0
        if ( rMergeFallback == MERGEFALLBACK_ADDFIRST )
391
0
            MergeItems( pToolbar, 0, 0, rItemId, rCommandMap, rModuleIdentifier, rItems );
392
0
        else if ( rMergeFallback == MERGEFALLBACK_ADDLAST )
393
0
            MergeItems( pToolbar, ToolBox::APPEND, 0, rItemId, rCommandMap, rModuleIdentifier, rItems );
394
0
        else
395
0
            return false;
396
0
        return true;
397
0
    }
398
399
0
    return false;
400
0
}
401
402
/**
403
 Merges (adds) toolbar items into an existing toolbar.
404
405
 @param
406
     pToolbar
407
408
     A valid pointer to the toolbar where the merge
409
     fall back operation is applied to.
410
411
 @param
412
     nPos
413
414
     The reference position of the toolbar item for
415
     the merge operation. Value must be between
416
     0 and number of toolbar items - 1.
417
418
 @param
419
     rItemId
420
421
     A unique item ID.
422
423
 @param
424
     rModuleIdentifier
425
426
     The current application module context.
427
428
 @param
429
     rItems
430
431
     Toolbar items which are associated to the merge
432
     command.
433
*/
434
void ToolBarMerger::MergeItems(
435
    ToolBox*                               pToolbar,
436
    ToolBox::ImplToolItems::size_type      nPos,
437
    sal_uInt16                             nModIndex,
438
    ToolBoxItemId&                         rItemId,
439
    CommandToInfoMap&                      rCommandMap,
440
    std::u16string_view                    rModuleIdentifier,
441
    const AddonToolbarItemContainer&       rAddonToolbarItems )
442
0
{
443
0
    const sal_Int32 nSize( rAddonToolbarItems.size() );
444
445
0
    for ( sal_Int32 i = 0; i < nSize; i++ )
446
0
    {
447
0
        const AddonToolbarItem& rItem = rAddonToolbarItems[i];
448
0
        if ( IsCorrectContext( rItem.aContext, rModuleIdentifier ))
449
0
        {
450
0
            ToolBox::ImplToolItems::size_type nInsPos = nPos;
451
0
            if (nInsPos != ToolBox::APPEND)
452
0
            {
453
0
                nInsPos += nModIndex+i;
454
0
                if ( nInsPos > pToolbar->GetItemCount() )
455
0
                    nInsPos = ToolBox::APPEND;
456
0
            }
457
458
0
            if ( rItem.aCommandURL == TOOLBOXITEM_SEPARATOR_STR )
459
0
                pToolbar->InsertSeparator( nInsPos );
460
0
            else
461
0
            {
462
0
                CommandToInfoMap::iterator pIter = rCommandMap.find( rItem.aCommandURL );
463
0
                if ( pIter == rCommandMap.end())
464
0
                {
465
0
                    CommandInfo aCmdInfo;
466
0
                    aCmdInfo.nId = rItemId;
467
0
                    rCommandMap.emplace(rItem.aCommandURL, aCmdInfo);
468
0
                }
469
0
                else
470
0
                {
471
0
                    pIter->second.aIds.push_back( rItemId );
472
0
                }
473
474
0
                ToolBarMerger::CreateToolbarItem( pToolbar, nInsPos, rItemId, rItem );
475
0
            }
476
477
0
            ++rItemId;
478
0
        }
479
0
    }
480
0
}
481
482
/**
483
 Replaces a toolbar item with new items for an
484
 existing toolbar.
485
486
 @param
487
     pToolbar
488
489
     A valid pointer to the toolbar where the merge
490
     fall back operation is applied to.
491
492
 @param
493
     nPos
494
495
     The reference position of the toolbar item for
496
     the merge operation. Value must be between
497
     0 and number of toolbar items - 1.
498
499
 @param
500
     rItemId
501
502
     A unique item ID.
503
504
 @param
505
     rModuleIdentifier
506
507
     The current application module context.
508
509
 @param
510
     rItems
511
512
     Toolbar items which are associated to the merge
513
     command.
514
*/
515
void ToolBarMerger::ReplaceItem(
516
    ToolBox*                               pToolbar,
517
    ToolBox::ImplToolItems::size_type      nPos,
518
    ToolBoxItemId&                         rItemId,
519
    CommandToInfoMap&                      rCommandMap,
520
    std::u16string_view                    rModuleIdentifier,
521
    const AddonToolbarItemContainer&       rAddonToolbarItems )
522
0
{
523
0
    pToolbar->RemoveItem( nPos );
524
0
    MergeItems( pToolbar, nPos, 0, rItemId, rCommandMap, rModuleIdentifier, rAddonToolbarItems );
525
0
}
526
527
/**
528
 Removes toolbar items from an existing toolbar.
529
530
 @param
531
     pToolbar
532
533
     A valid pointer to the toolbar where the merge
534
     fall back operation is applied to.
535
536
 @param
537
     nPos
538
539
     The reference position of the toolbar item for
540
     the merge operation. Value must be between
541
     0 and number of toolbar items - 1.
542
543
 @param
544
     rMergeCommandParameter.
545
546
     An optional argument for the merge command.
547
*/
548
void ToolBarMerger::RemoveItems(
549
    ToolBox*                  pToolbar,
550
    ToolBox::ImplToolItems::size_type nPos,
551
    std::u16string_view rMergeCommandParameter )
552
0
{
553
0
    sal_Int32 nCount = o3tl::toInt32(rMergeCommandParameter);
554
0
    if ( nCount > 0 )
555
0
    {
556
0
        for ( sal_Int32 i = 0; i < nCount; i++ )
557
0
        {
558
0
            if ( nPos < pToolbar->GetItemCount() )
559
0
                pToolbar->RemoveItem( nPos );
560
0
        }
561
0
    }
562
0
}
563
564
/**
565
 Removes toolbar items from an existing toolbar.
566
567
 @param
568
     pToolbar
569
570
     A valid pointer to the toolbar where the merge
571
     fall back operation is applied to.
572
573
 @param
574
     nPos
575
576
     The reference position of the toolbar item for
577
     the merge operation. Value must be between
578
     0 and number of toolbar items - 1.
579
580
 @param
581
     rMergeCommandParameter.
582
583
     An optional argument for the merge command.
584
585
 @result
586
     Returns true for a successful operation otherwise
587
     false.
588
*/
589
rtl::Reference<::cppu::OWeakObject> ToolBarMerger::CreateController(
590
    const uno::Reference< uno::XComponentContext >& rxContext,
591
    const uno::Reference< frame::XFrame > & xFrame,
592
    ToolBox*               pToolbar,
593
    const OUString& rCommandURL,
594
    ToolBoxItemId          nId,
595
    sal_uInt16             nWidth,
596
    std::u16string_view rControlType )
597
0
{
598
0
    rtl::Reference<::cppu::OWeakObject> pResult;
599
600
0
    if ( rControlType == TOOLBARCONTROLLER_BUTTON )
601
0
        pResult = new ButtonToolbarController( rxContext, pToolbar, rCommandURL );
602
0
    else if ( rControlType == TOOLBARCONTROLLER_COMBOBOX )
603
0
        pResult = new ComboboxToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL );
604
0
    else if ( rControlType == TOOLBARCONTROLLER_EDIT )
605
0
        pResult = new EditToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL );
606
0
    else if ( rControlType == TOOLBARCONTROLLER_SPINFIELD )
607
0
        pResult = new SpinfieldToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL );
608
0
    else if ( rControlType == TOOLBARCONTROLLER_IMGBUTTON )
609
0
        pResult = new ImageButtonToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL );
610
0
    else if ( rControlType == TOOLBARCONTROLLER_DROPDOWNBOX )
611
0
        pResult = new DropdownToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL );
612
0
    else if ( rControlType == TOOLBARCONTROLLER_DROPDOWNBTN )
613
0
        pResult = new ToggleButtonToolbarController( rxContext, xFrame, pToolbar, nId,
614
0
                                                     ToggleButtonToolbarController::Style::DropDownButton, rCommandURL );
615
0
    else if ( rControlType == TOOLBARCONTROLLER_FIXEDIMAGE )
616
0
        pResult = new FixedImageToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL );
617
0
    else if ( rControlType == TOOLBARCONTROLLER_FIXEDTEXT )
618
0
        pResult = new FixedTextToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL );
619
0
    else if ( rControlType == TOOLBARCONTROLLER_TOGGLEDDBTN )
620
0
        pResult = new ToggleButtonToolbarController( rxContext, xFrame, pToolbar, nId,
621
0
                                                     ToggleButtonToolbarController::Style::ToggleDropDownButton, rCommandURL );
622
0
    else
623
0
        pResult = new GenericToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL );
624
625
0
    return pResult;
626
0
}
627
628
void ToolBarMerger::CreateToolbarItem( ToolBox* pToolbar, ToolBox::ImplToolItems::size_type nPos, ToolBoxItemId nItemId, const AddonToolbarItem& rItem )
629
0
{
630
0
    assert(pToolbar->GetItemData(nItemId) == nullptr); // that future would contain a double free
631
632
0
    pToolbar->InsertItem( nItemId, rItem.aLabel, rItem.aCommandURL, ToolBoxItemBits::NONE, nPos );
633
0
    pToolbar->SetQuickHelpText( nItemId, rItem.aLabel );
634
0
    pToolbar->SetItemText( nItemId, rItem.aLabel );
635
0
    pToolbar->EnableItem( nItemId );
636
0
    pToolbar->SetItemState( nItemId, TRISTATE_FALSE );
637
638
    // Use the user data to store add-on specific data with the toolbar item
639
0
    AddonsParams* pAddonParams = new AddonsParams;
640
0
    pAddonParams->aControlType = rItem.aControlType;
641
0
    pAddonParams->nWidth       = rItem.nWidth;
642
0
    pToolbar->SetItemData( nItemId, pAddonParams );
643
0
}
644
645
} // namespace framework
646
647
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */