3 Oct 2024

Setting dialogs that are available via UNO Commands

LibreOffice options page provides rich set of settings for everyone who wants to tune LibreOffice to match their needs. But, what if you as a developer, need setting dialogs that are needed elsewhere in the LibreOffice application? Here I discuss some of such use cases, which are handled by defining UNO commands.

Options Page

The code for providing “Tools > Options” is not in a single module, but main part resides in cui module, which contains code which is used across different modules. Looking into cui/source/options/ folder from LibreOffice core source code, you can see various different source files related to the options. The biggest file there is cui/source/options/treeopt.cxx, which is the actual implementation of the tree-based dialog that you see when you open Tools > Options dialog. There are other C++ files that handle .ui files related to options. You can find those UI files in cui/uiconfig/ui/ folder with a name like opt*.ui:

$ ls cui/uiconfig/ui/opt*.ui

These files can be edited and they are used as described in the LibreOffice design blog:

UNO Dispatch Commands

Only some of the dialogs can be opened available via UNO dispatch commands. As an example, you may see “.uno:AdditionsDialog” is used both in cui/source/options/optgdlg.cxx for creating a dialog in Tools > Options (when you click for “more icons”), and also in sfx2/source/appl/appserv.cxx.

You can try running this UNO command in LibreOffice BASIC editor with this code snippet:

Sub Main()
    Set oDispatch = CreateUnoService("com.sun.star.frame.DispatchHelper")
    Dim args(0) As New com.sun.star.beans.PropertyValue
    Set oFrame = StarDesktop.Frames.getByIndex(0)
    oDispatch.executeDispatch(oFrame, ".uno:AdditionsDialog", "", 0, args)
End Sub

The above command is defined specifically to help developers use the “Extensions” dialog, anywhere in LibreOffice UI, from top menus to context menus and toolbars and also in code, in a simple way.

"Extensions

There is another dialog titled “Security Options and Warnings”, which is opened through .uno:OptionsSecurityDialog UNO command. In this way, it can be used easily in other modules of LibreOffice.

SecurityOptionsDialog

SecurityOptionsDialog

Implementing UNO Command

Adding a new UNO command was discussed before, in a separate blog post:

Adding a new UNO command

Adding a new UNO command for an options dialog is basically the same. There can be differences regarding the configurations and the data that is passed between the dialog and the caller.

When you create a dialog box directly like the code snippet below, you have access to the member functions defined for that specific dialog:

IMPL_LINK_NOARG( SwGlossaryDlg, PathHdl, weld::Button&, void )
{
    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
    ScopedVclPtr<AbstractSvxMultiPathDialog> pDlg(pFact->CreateSvxPathSelectDialog(m_xDialog.get()));
    SvtPathOptions aPathOpt;
    const OUString sGlosPath( aPathOpt.GetAutoTextPath() );
    pDlg->SetPath(sGlosPath);
    if(RET_OK == pDlg->Execute())
    {
        const OUString sTmp(pDlg->GetPath());
        if(sTmp != sGlosPath)
        {
            aPathOpt.SetAutoTextPath( sTmp );
            ::GetGlossaries()->UpdateGlosPath( true );
            Init();
        }
    }
}

As you can see, pDlg->GetPath() is accessible here, and you can use it to pass data. But when you are using UNO commands, those functions will not be available directly. Instead, you may pass values that denote the data that will be read from somewhere else, like the configuration.

For example, consider there are multiple paths that you may want to edit using this UNO command with the same dialog. In this case, you can pass a value that shows the associated path that you are changing. It can be passed as an enumeration, and then you set and/or get the value directly from the configuration.

In this way, the callers in the C++ code will have much easier task to do, as it is only calling the UNO command, and the rest is done in the implementation of the UNO command.

For AdditionsDialog, the calling code is as simple as this in cui/source/options/optgdlg.cxx:

IMPL_STATIC_LINK_NOARG(OfaViewTabPage, OnMoreIconsClick, weld::Button&, void)
{
    css::uno::Sequence<css::beans::PropertyValue> aArgs{ comphelper::makePropertyValue(
u"AdditionsTag"_ustr, u"Icons"_ustr) };
    comphelper::dispatchCommand(u".uno:AdditionsDialog"_ustr, aArgs);
}

Passing Parameters to UNO Commands

UNO dispatch commands can take parameters. As an example, take a look at .uno:NewDoc defined in sfx2/sdi/sfx.sdi:

SfxStringItem NewDoc SID_NEWDOC
(SfxStringItem Region SID_TEMPLATE_REGIONNAME,SfxStringItem Name SID_TEMPLATE_NAME)
[
...
]

As you can see, there are two parameters:

SfxStringItem Region SID_TEMPLATE_REGIONNAME SfxStringItem Name SID_TEMPLATE_NAME

The SfxStringItem is the type, Region and Name are the names of the parameters, SID_TEMPLATE_REGIONNAME and SID_TEMPLATE_NAME are the constants used for passing parameters. The parameter type is not limited to numbers and strings, and it can be any defined class.

To set and get data for this parameters, you may use appropriate Set and Put functions. For example, this gets the parameter if set:

const SfxStringItem *pItem = rSet.GetItemIfSet( SID_TEMPLATE_REGIONNAME, false)

Or, this sets the data:

OUString sVal = u"test"_ustr;

rSet.Put( SfxStringItem( SID_TEMPLATE_REGIONNAME, sVal ) );

Final Notes

To get to know better how to implement more complex UNO dispatch commands, you can refer to the implementation of the existing UNO commands to get idea about how they are implemented. You can see a comprehensive list of UNO commands here:

15 Aug 2024

Extending the UNO API

Various functionalities of the LibreOffice are available through its programming interface, the UNO API. Here I discuss how to extend it. (more…)

29 Jul 2024

Fuzz testing to maintain LibreOffice code quality

Here I discuss what fuzz testing is, and how LibreOffice developers use it incrementally to maintain LibreOffice code quality. (more…)

25 Jul 2024

LibreOfficeKit for document conversion

In the previous blog post, I provided a brief introduction to LibreOfficeKit API which one can use for accessing LibreOffice functionalities in an external application. Here I discuss in detail how to use LibreOfficeKit for converting an ODT to PDF, or from/to virtually any other format that LibreOffice supports. (more…)

27 Jun 2024

LibreOfficeKit API in action

If you want to use LibreOffice functionality in your applications, LibreOfficeKit API is one of the good ways to do that. Here I describe how, with some examples. If you want to add the capability of loading, displaying, editing, saving and/or converting LibreOffice/MS Office files to your application, you have come to a good place. (more…)

30 May 2024

Porting Java tests to C++

In this blog post, I discuss porting Java tests from Java to C++. We have many Java tests, and porting them to C++ is beneficial for LibreOffice. Here I discuss why, and how. (more…)

14 May 2024

Crash fixes, part 4: assertion failure

In the previous parts of the blog posts series on fixing software crashes, I have written about some crash fixes in LibreOffice around segfaults, aborts, and I discussed how test them. Here I write about fixing assertion failure. (more…)

18 Apr 2024

Crash fixes part 3 – Testing crashes

I have previously discussed fixing crashes in 2 parts (segfaults, aborts). Here I discuss testing crashes to avoid creating re-creating regressions. (more…)

18 Mar 2024

Test improvement – More and better tests for LibreOffice

One of the areas that can help LibreOffice, but may not directly be visible to the users even though it has a big impact is the quality assurance, is automated testing.  Here, I discuss some areas and notes around improving tests for LibreOffice. First, I start with regressions and bug fixes without a test. (more…)

29 Feb 2024

Writer tables converted to plain text – difficultyInteresting EasyHack

If you copy contents from LibreOffice Writer to a plain text editor like gedit or Notepad, you will see that it does a straightforward thing: It copies the text and some basic formatting like converting bullets to ‘•’. For the Writer tables, the conversion is very simple right now: every cell is written in a separate line. (more…)