desktop/source/lib/init.cxx   |   27 +++++++++++++++++++++++++++
 include/vcl/svapp.hxx         |    7 +++++++
 vcl/inc/salinst.hxx           |    4 ++++
 vcl/source/window/builder.cxx |   35 +++++++++++++++++++++++++++++++++--
 4 files changed, 71 insertions(+), 2 deletions(-)

New commits:
commit b749f045bc85b59c4c21774782c6c99a5f035bb2
Author:     Caolán McNamara <[email protected]>
AuthorDate: Mon Dec 8 12:11:41 2025 +0000
Commit:     Caolán McNamara <[email protected]>
CommitDate: Wed Dec 10 16:08:55 2025 +0100

    put the uicoverage into the first level json
    
    i.e. don't put json into json
    
    Change-Id: I5606c0d280e7f8c3c08cc21e1bc62689de7422bf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195226
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195315
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 4956371df9f8..ca25346f9b2a 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5615,7 +5615,7 @@ static void doc_postUnoCommand(LibreOfficeKitDocument* 
pThis, const char* pComma
                     tools::JsonWriter aJson;
                     aJson.put("commandName", aCommand);
                     aJson.put("success", true);
-                    aJson.put("result", Application::UICoverageReport());
+                    Application::UICoverageReport(aJson);
                     
pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT,
 aJson.finishAndGetAsOString());
                 }
             }
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 2bfbc02a104f..5b4e079c958e 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -45,6 +45,7 @@
 
 
 class Bitmap;
+namespace tools { class JsonWriter; }
 namespace weld
 {
     class Builder;
@@ -1241,7 +1242,7 @@ public:
     static void                 EnableUICoverage(bool bEnable);
 
     /** Report on what .ui files were used*/
-    static OString              UICoverageReport();
+    static void UICoverageReport(tools::JsonWriter& rJson);
 
     ///@}
 
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index f73a8b444653..30e881eacb07 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -194,18 +194,16 @@ void Application::EnableUICoverage(bool bEnable)
         ImplGetSVData()->mpDefInst->getUsedUIList().clear();
 }
 
-OString Application::UICoverageReport()
+void Application::UICoverageReport(tools::JsonWriter& rJson)
 {
-    tools::JsonWriter aJson;
+    auto resultNode = rJson.startNode("result");
 
     const auto& entries = ImplGetSVData()->mpDefInst->getUsedUIList();
     {
-        auto childrenNode = aJson.startArray("used");
+        auto childrenNode = rJson.startArray("used");
         for (const auto& entry : entries)
-            aJson.putSimpleValue(entry);
+            rJson.putSimpleValue(entry);
     }
-
-    return aJson.finishAndGetAsOString();
 }
 
 std::unique_ptr<weld::Builder> Application::CreateBuilder(weld::Widget* 
pParent, const OUString &rUIFile, bool bMobile, sal_uInt64 nLOKWindowId)
commit be0e1382a6964a3edc62d9b3317eef9170eb588a
Author:     Caolán McNamara <[email protected]>
AuthorDate: Fri Dec 5 20:22:22 2025 +0000
Commit:     Caolán McNamara <[email protected]>
CommitDate: Wed Dec 10 16:08:46 2025 +0100

    Collect .ui use coverage information
    
    bootstrap reporting of what .ui files were used in a session.
    
    Change-Id: I19b004482a3892898a9738e5e98ee084ab8cdcec
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195113
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195314
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 47b4e4e56cbd..4956371df9f8 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5602,6 +5602,33 @@ static void doc_postUnoCommand(LibreOfficeKitDocument* 
pThis, const char* pComma
         hideSidebar();
         return;
     }
+    else if (gImpl && aCommand == ".uno:UICoverage")
+    {
+        for (const beans::PropertyValue& rPropValue : aPropertyValuesVector)
+        {
+            if (rPropValue.Name == "Report")
+            {
+                bool report(true);
+                rPropValue.Value >>= report;
+                if (report)
+                {
+                    tools::JsonWriter aJson;
+                    aJson.put("commandName", aCommand);
+                    aJson.put("success", true);
+                    aJson.put("result", Application::UICoverageReport());
+                    
pDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_UNO_COMMAND_RESULT,
 aJson.finishAndGetAsOString());
+                }
+            }
+            else if (rPropValue.Name == "Track")
+            {
+                bool track(false);
+                rPropValue.Value >>= track;
+                Application::EnableUICoverage(track);
+            }
+        }
+
+        return;
+    }
 
     if (aCommand != ".uno:Save")
     {
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 43cb3f9535b0..2bfbc02a104f 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -1237,6 +1237,12 @@ public:
     /** Determines if safe mode is enabled */
     static bool                 IsSafeModeEnabled();
 
+    /** Collect what .ui files are used*/
+    static void                 EnableUICoverage(bool bEnable);
+
+    /** Report on what .ui files were used*/
+    static OString              UICoverageReport();
+
     ///@}
 
     /** Get the desktop environment the process is currently running in
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index 359cf21226be..65b64125697b 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -20,6 +20,7 @@
 #pragma once
 
 #include <sal/types.h>
+#include <o3tl/sorted_vector.hxx>
 #include <rtl/ref.hxx>
 #include <vcl/ColorDialog.hxx>
 #include <vcl/dllapi.h>
@@ -81,6 +82,7 @@ private:
     rtl::Reference< vcl::DisplayConnectionDispatch > m_pEventInst;
     const std::unique_ptr<comphelper::SolarMutex> m_pYieldMutex;
     css::uno::Reference<css::datatransfer::clipboard::XClipboard> m_clipboard;
+    o3tl::sorted_vector<OUString> m_usedUI;
 
 protected:
     bool m_bSupportsOpenGL = false;
@@ -95,6 +97,8 @@ public:
 
     bool supportsOpenGL() const { return m_bSupportsOpenGL; }
 
+    o3tl::sorted_vector<OUString>& getUsedUIList() { return m_usedUI; }
+
     //called directly after Application::Init
     virtual void            AfterAppInit() {}
     virtual bool            SVMainHook(int*) { return false; }
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index df072d404ca3..f73a8b444653 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -185,8 +185,36 @@ namespace
 
 }
 
+static bool bEnableUICoverage = false;
+
+void Application::EnableUICoverage(bool bEnable)
+{
+    bEnableUICoverage = bEnable;
+    if (!bEnableUICoverage)
+        ImplGetSVData()->mpDefInst->getUsedUIList().clear();
+}
+
+OString Application::UICoverageReport()
+{
+    tools::JsonWriter aJson;
+
+    const auto& entries = ImplGetSVData()->mpDefInst->getUsedUIList();
+    {
+        auto childrenNode = aJson.startArray("used");
+        for (const auto& entry : entries)
+            aJson.putSimpleValue(entry);
+    }
+
+    return aJson.finishAndGetAsOString();
+}
+
 std::unique_ptr<weld::Builder> Application::CreateBuilder(weld::Widget* 
pParent, const OUString &rUIFile, bool bMobile, sal_uInt64 nLOKWindowId)
 {
+    ImplSVData* pSVData = ImplGetSVData();
+
+    if (bEnableUICoverage)
+        pSVData->mpDefInst->getUsedUIList().insert(rUIFile);
+
     if (comphelper::LibreOfficeKit::isActive() && 
!jsdialog::isIgnored(rUIFile))
     {
         if (jsdialog::isBuilderEnabledForSidebar(rUIFile))
@@ -208,11 +236,16 @@ std::unique_ptr<weld::Builder> 
Application::CreateBuilder(weld::Widget* pParent,
             SAL_WARN("vcl", "UI file not enabled for JSDialogs: " << rUIFile);
     }
 
-    return ImplGetSVData()->mpDefInst->CreateBuilder(pParent, 
AllSettings::GetUIRootDir(), rUIFile);
+    return pSVData->mpDefInst->CreateBuilder(pParent, 
AllSettings::GetUIRootDir(), rUIFile);
 }
 
 std::unique_ptr<weld::Builder> Application::CreateInterimBuilder(vcl::Window* 
pParent, const OUString &rUIFile, bool bAllowCycleFocusOut, sal_uInt64 
nLOKWindowId)
 {
+    ImplSVData* pSVData = ImplGetSVData();
+
+    if (bEnableUICoverage)
+        pSVData->mpDefInst->getUsedUIList().insert(rUIFile);
+
     if (comphelper::LibreOfficeKit::isActive() && 
!jsdialog::isIgnored(rUIFile))
     {
         // Notebookbar sub controls
@@ -228,7 +261,7 @@ std::unique_ptr<weld::Builder> 
Application::CreateInterimBuilder(vcl::Window* pP
             SAL_WARN("vcl", "UI file not enabled for JSDialogs: " << rUIFile);
     }
 
-    return ImplGetSVData()->mpDefInst->CreateInterimBuilder(pParent, 
AllSettings::GetUIRootDir(), rUIFile, bAllowCycleFocusOut, nLOKWindowId);
+    return pSVData->mpDefInst->CreateInterimBuilder(pParent, 
AllSettings::GetUIRootDir(), rUIFile, bAllowCycleFocusOut, nLOKWindowId);
 }
 
 weld::MessageDialog* Application::CreateMessageDialog(weld::Widget* pParent, 
VclMessageType eMessageType,

Reply via email to