use tools::JsonWriter for dumping property tree

Change-Id: I8f55af19ba10b71bd621e69b27000ab7cb565309
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96677
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 075ca30..20ec8c0 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -4769,7 +4769,7 @@ static char* getTrackedChanges(LibreOfficeKitDocument* pThis)
        {
            uno::Reference<beans::XPropertySet> xRedline(xRedlines->nextElement(), uno::UNO_QUERY);
            auto redlineNode = aJson.startNode("");
            aJson.put("index", nIndex);
            aJson.put("index", static_cast<sal_Int32>(nIndex));

            OUString sAuthor;
            xRedline->getPropertyValue("RedlineAuthor") >>= sAuthor;
diff --git a/include/sfx2/sidebar/Deck.hxx b/include/sfx2/sidebar/Deck.hxx
index 21e7dfa..e8f00b6 100644
--- a/include/sfx2/sidebar/Deck.hxx
+++ b/include/sfx2/sidebar/Deck.hxx
@@ -69,7 +69,7 @@ public:
    virtual bool EventNotify(NotifyEvent& rEvent) override;
    virtual void Resize() override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;

    static void PrintWindowSubTree (vcl::Window* pRoot, int nIndentation);

diff --git a/include/sfx2/sidebar/Panel.hxx b/include/sfx2/sidebar/Panel.hxx
index cae82bb..ee63522 100644
--- a/include/sfx2/sidebar/Panel.hxx
+++ b/include/sfx2/sidebar/Panel.hxx
@@ -69,7 +69,7 @@ public:
    virtual void Resize() override;
    virtual void DataChanged (const DataChangedEvent& rEvent) override;
    virtual void ApplySettings(vcl::RenderContext& rRenderContext) override;
    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;

private:
    const OUString msPanelId;
diff --git a/include/svtools/ctrlbox.hxx b/include/svtools/ctrlbox.hxx
index 301a9c1..4b5035f 100644
--- a/include/svtools/ctrlbox.hxx
+++ b/include/svtools/ctrlbox.hxx
@@ -373,7 +373,7 @@ public:
    void grab_focus() { m_xComboBox->grab_focus(); }
    bool has_focus() const { return m_xComboBox->has_focus(); }
    void connect_entry_activate(const Link<weld::ComboBox&, bool>& rLink) { m_xComboBox->connect_entry_activate(rLink); }
    void connect_get_property_tree(const Link<boost::property_tree::ptree&, void>& rLink) { m_xComboBox->connect_get_property_tree(rLink); }
    void connect_get_property_tree(const Link<tools::JsonWriter&, void>& rLink) { m_xComboBox->connect_get_property_tree(rLink); }
    void set_entry_width_chars(int nWidth) { m_xComboBox->set_entry_width_chars(nWidth); }
    void set_size_request(int nWidth, int nHeight) { m_xComboBox->set_size_request(nWidth, nHeight); }
    int get_max_mru_count() { return m_xComboBox->get_max_mru_count(); }
@@ -486,7 +486,7 @@ public:
    bool has_focus() const { return m_xComboBox->has_focus(); }
    void connect_entry_activate(const Link<weld::ComboBox&, bool>& rLink) { m_xComboBox->connect_entry_activate(rLink); }
    void disable_entry_completion() { m_xComboBox->set_entry_completion(false, false); }
    void connect_get_property_tree(const Link<boost::property_tree::ptree&, void>& rLink) { m_xComboBox->connect_get_property_tree(rLink); }
    void connect_get_property_tree(const Link<tools::JsonWriter&, void>& rLink) { m_xComboBox->connect_get_property_tree(rLink); }

private:
    FontSizeBox(const FontSizeBox&) = delete;
diff --git a/include/svx/fillctrl.hxx b/include/svx/fillctrl.hxx
index b896fda..b81dfb4 100644
--- a/include/svx/fillctrl.hxx
+++ b/include/svx/fillctrl.hxx
@@ -88,7 +88,7 @@ private:
    DECL_LINK(AttrKeyInputHdl, const KeyEvent&, bool);
    DECL_LINK(TypeKeyInputHdl, const KeyEvent&, bool);
    DECL_LINK(ColorKeyInputHdl, const KeyEvent&, bool);
    DECL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void);
    DECL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, tools::JsonWriter&, void);
    DECL_LINK(AttrFocusHdl, weld::Widget&, void);
    DECL_LINK(TypeFocusHdl, weld::Widget&, void);

diff --git a/include/tools/json_writer.hxx b/include/tools/json_writer.hxx
index c15c4b7..3b27a18 100644
--- a/include/tools/json_writer.hxx
+++ b/include/tools/json_writer.hxx
@@ -52,7 +52,18 @@ public:
    void put(const char* pPropName, const OUString& rPropValue);
    void put(const char* pPropName, const OString& rPropValue);
    void put(const char* pPropName, const char* pPropVal);
    void put(const char*, int);
    void put(const char* pPropName, const std::string& rPropValue)
    {
        put(pPropName, rPropValue.data());
    }

    void put(const char* pPropName, sal_uInt16 nPropVal) { put(pPropName, sal_Int64(nPropVal)); }
    void put(const char* pPropName, sal_Int16 nPropVal) { put(pPropName, sal_Int64(nPropVal)); }
    void put(const char* pPropName, sal_Int32 nPropVal) { put(pPropName, sal_Int64(nPropVal)); }
    void put(const char* pPropName, sal_uInt32 nPropVal) { put(pPropName, sal_Int64(nPropVal)); }
    void put(const char* pPropName, sal_Int64);
    void put(const char* pPropName, bool);
    void put(const char* pPropName, double);

    /// This assumes that this data belongs at this point in the stream, and is valid, and properly encoded
    void putRaw(const rtl::OStringBuffer&);
@@ -61,6 +72,10 @@ public:
     * after this no more document modifications may be written. */
    char* extractData();
    OString extractAsOString();
    std::string extractAsStdString();

    /** returns true if the current JSON data matches the string */
    bool isDataEquals(const std::string&);

private:
    void endNode();
diff --git a/include/vcl/button.hxx b/include/vcl/button.hxx
index 1d06258..3f998d5 100644
--- a/include/vcl/button.hxx
+++ b/include/vcl/button.hxx
@@ -92,7 +92,7 @@ public:

    virtual FactoryFunction GetUITestFactory() const override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;

protected:

@@ -330,7 +330,7 @@ public:
    virtual void ShowFocus(const tools::Rectangle& rRect) override;

    /// Button hes additional stuff that we need to dump too.
    boost::property_tree::ptree DumpAsPropertyTree() override;
    void DumpAsPropertyTree(tools::JsonWriter&) override;

    virtual FactoryFunction GetUITestFactory() const override;
};
@@ -421,7 +421,7 @@ public:
    virtual void ShowFocus(const tools::Rectangle& rRect) override;

    /// Button hes additional stuff that we need to dump too.
    boost::property_tree::ptree DumpAsPropertyTree() override;
    void DumpAsPropertyTree(tools::JsonWriter&) override;

    virtual FactoryFunction GetUITestFactory() const override;
};
diff --git a/include/vcl/field.hxx b/include/vcl/field.hxx
index 24a6eab7..92cfbbf 100644
--- a/include/vcl/field.hxx
+++ b/include/vcl/field.hxx
@@ -366,7 +366,7 @@ public:
    virtual bool            set_property(const OString &rKey, const OUString &rValue) override;
    virtual void            dispose() override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
};

class UNLESS_MERGELIBS(VCL_DLLPUBLIC) DateField : public SpinField, public DateFormatter
diff --git a/include/vcl/fmtfield.hxx b/include/vcl/fmtfield.hxx
index c61aca9..be6c82f 100644
--- a/include/vcl/fmtfield.hxx
+++ b/include/vcl/fmtfield.hxx
@@ -237,7 +237,7 @@ public:
    void    UseInputStringForFormatting();
    bool    IsUsingInputStringForFormatting() const { return m_bUseInputStringForFormatting;}

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;

    virtual FactoryFunction GetUITestFactory() const override;

diff --git a/include/vcl/layout.hxx b/include/vcl/layout.hxx
index 9caa0c8..cee1621 100644
--- a/include/vcl/layout.hxx
+++ b/include/vcl/layout.hxx
@@ -104,7 +104,7 @@ public:
        return m_bVerticalContainer;
    }
    virtual bool set_property(const OString &rKey, const OUString &rValue) override;
    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
protected:
    virtual sal_uInt16 getDefaultAccessibleRole() const override;
    void accumulateMaxes(const Size &rChildSize, Size &rSize) const;
@@ -335,7 +335,7 @@ private:
    Size calculateRequisitionForSpacings(sal_Int32 nRowSpacing, sal_Int32 nColSpacing) const;
    virtual Size calculateRequisition() const override;
    virtual void setAllocation(const Size &rAllocation) override;
    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
public:
    VclGrid(vcl::Window *pParent)
        : VclContainer(pParent)
@@ -447,7 +447,7 @@ public:
    virtual const vcl::Window *get_child() const override;
    vcl::Window *get_label_widget();
    const vcl::Window *get_label_widget() const;
    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
private:
    virtual Size calculateRequisition() const override;
    virtual void setAllocation(const Size &rAllocation) override;
@@ -807,7 +807,7 @@ public:
        m_xTransferHelper = rHelper;
        m_nDragAction = eDNDConstants;
    }
    boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
};

//Get first window of a pTopLevel window as
diff --git a/include/vcl/tabctrl.hxx b/include/vcl/tabctrl.hxx
index d35f0d7..798b5ac37 100644
--- a/include/vcl/tabctrl.hxx
+++ b/include/vcl/tabctrl.hxx
@@ -187,7 +187,7 @@ public:

    virtual void queue_resize(StateChangedType eReason = StateChangedType::Layout) override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
};

class NotebookBar;
diff --git a/include/vcl/toolbox.hxx b/include/vcl/toolbox.hxx
index e60fb642..6987f77 100644
--- a/include/vcl/toolbox.hxx
+++ b/include/vcl/toolbox.hxx
@@ -506,7 +506,7 @@ public:

    void SetLineSpacing(bool b) { mbLineSpacing = b; }

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
};

inline void ToolBox::CheckItem( sal_uInt16 nItemId, bool bCheck )
diff --git a/include/vcl/toolkit/field.hxx b/include/vcl/toolkit/field.hxx
index e78b174..dacaed6 100644
--- a/include/vcl/toolkit/field.hxx
+++ b/include/vcl/toolkit/field.hxx
@@ -101,7 +101,7 @@ public:
    virtual bool            set_property(const OString &rKey, const OUString &rValue) override;
    virtual void            dispose() override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
    virtual FactoryFunction GetUITestFactory() const override;
};

diff --git a/include/vcl/toolkit/lstbox.hxx b/include/vcl/toolkit/lstbox.hxx
index 7ae5c99..01f76b5 100644
--- a/include/vcl/toolkit/lstbox.hxx
+++ b/include/vcl/toolkit/lstbox.hxx
@@ -254,7 +254,7 @@ public:

    virtual FactoryFunction GetUITestFactory() const override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
};

class UNLESS_MERGELIBS(VCL_DLLPUBLIC) MultiListBox final : public ListBox
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 2e0134a..fe03d0e 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -27,8 +27,6 @@
#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
#include <com/sun/star/accessibility/XAccessible.hpp>

#include <boost/property_tree/ptree_fwd.hpp>

#include <assert.h>
#include <memory>
#include <vector>
@@ -76,6 +74,10 @@ namespace vcl
class ILibreOfficeKitNotifier;
typedef OutputDevice RenderContext;
}
namespace tools
{
class JsonWriter;
}

namespace weld
{
@@ -264,8 +266,7 @@ public:

    virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() = 0;

    virtual void connect_get_property_tree(const Link<boost::property_tree::ptree&, void>& rLink)
        = 0;
    virtual void connect_get_property_tree(const Link<tools::JsonWriter&, void>& rLink) = 0;

    // render the widget to an output device
    virtual void draw(VirtualDevice& rOutput) = 0;
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 0ba3dc3..c4cd34f 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -34,8 +34,6 @@
#include <com/sun/star/uno/Reference.hxx>
#include <memory>

#include <boost/property_tree/ptree_fwd.hpp>

class VirtualDevice;
struct ImplSVEvent;
struct ImplWinData;
@@ -101,6 +99,7 @@ namespace svt { class PopupWindowControllerImpl; }
namespace weld { class Window; }

template<class T> class VclPtr;
namespace tools { class JsonWriter; }

enum class TrackingEventFlags
{
@@ -1212,7 +1211,7 @@ public:
    static bool                         IsLOKWindowsEmpty();

    /// Dumps itself and potentially its children to a property tree, to be written easily to JSON.
    virtual boost::property_tree::ptree DumpAsPropertyTree();
    virtual void DumpAsPropertyTree(tools::JsonWriter&);

    /// Same as MouseButtonDown(), but coordinates are in logic unit. used for LOK
    virtual void LogicMouseButtonDown(const MouseEvent&) {};
@@ -1575,7 +1574,7 @@ public:
    void SetHelpHdl(const Link<vcl::Window&, bool>& rLink);
    void SetMnemonicActivateHdl(const Link<vcl::Window&, bool>& rLink);
    void SetModalHierarchyHdl(const Link<bool, void>& rLink);
    void SetDumpAsPropertyTreeHdl(const Link<boost::property_tree::ptree&, void>& rLink);
    void SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink);
};

}
diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx
index f734224..ab1714d 100644
--- a/sc/source/core/tool/chgtrack.cxx
+++ b/sc/source/core/tool/chgtrack.cxx
@@ -4682,7 +4682,7 @@ static void lcl_getTrackedChange(ScDocument* pDoc, int nIndex, const ScChangeAct
    if (pAction->GetType() == SC_CAT_CONTENT)
    {
        auto redlinesNode = rRedlines.startNode("");
        rRedlines.put("index", nIndex);
        rRedlines.put("index", static_cast<sal_Int64>(nIndex));

        rRedlines.put("author", pAction->GetUser());

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 4cc2874..765ef9a 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2564,8 +2564,8 @@ void ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle, tools::J
        {
            auto node = rJsonWriter.startStruct();
            rJsonWriter.put("text", nStartRow + 1);
            rJsonWriter.put("size",nTotalPixels);
            rJsonWriter.put("groupLevels", nRowGroupDepth);
            rJsonWriter.put("size", nTotalPixels);
            rJsonWriter.put("groupLevels", static_cast<sal_Int64>(nRowGroupDepth));
        }

        std::vector<long> aRowGroupStartPositions(nRowGroupDepth, -nTotalPixels);
@@ -2703,9 +2703,9 @@ void ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle, tools::J
        if (nStartCol != nEndCol)
        {
            auto node = rJsonWriter.startStruct();
            rJsonWriter.put("text", nStartCol + 1);
            rJsonWriter.put("text", static_cast<sal_Int64>(nStartCol + 1));
            rJsonWriter.put("size", nTotalPixels);
            rJsonWriter.put("groupLevels", nColGroupDepth);
            rJsonWriter.put("groupLevels", static_cast<sal_Int64>(nColGroupDepth));
        }

        std::vector<long> aColGroupStartPositions(nColGroupDepth, -nTotalPixels);
diff --git a/sd/source/ui/sidebar/SlideBackground.cxx b/sd/source/ui/sidebar/SlideBackground.cxx
index df3a3be..cf9191b 100644
--- a/sd/source/ui/sidebar/SlideBackground.cxx
+++ b/sd/source/ui/sidebar/SlideBackground.cxx
@@ -273,14 +273,14 @@ void SlideBackground::Initialize()
    UpdateMarginBox();
}

boost::property_tree::ptree SlideBackground::DumpAsPropertyTree()
void SlideBackground::DumpAsPropertyTree(::tools::JsonWriter& rJsonWriter)
{
    if (mxPaperSizeBox->get_active() == -1)
    {
        mpBindings->Update(SID_ATTR_PAGE_SIZE);
    }

    return Control::DumpAsPropertyTree();
    Control::DumpAsPropertyTree(rJsonWriter);
}

void SlideBackground::HandleContextChange(
diff --git a/sd/source/ui/sidebar/SlideBackground.hxx b/sd/source/ui/sidebar/SlideBackground.hxx
index c4b9151..adc9e3b 100644
--- a/sd/source/ui/sidebar/SlideBackground.hxx
+++ b/sd/source/ui/sidebar/SlideBackground.hxx
@@ -73,7 +73,7 @@ public:

    virtual void HandleContextChange(
        const vcl::EnumContext& rContext) override;
    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(::tools::JsonWriter&) override;

private:

diff --git a/sfx2/source/sidebar/Deck.cxx b/sfx2/source/sidebar/Deck.cxx
index d96305c..3088eb245 100644
--- a/sfx2/source/sidebar/Deck.cxx
+++ b/sfx2/source/sidebar/Deck.cxx
@@ -35,7 +35,7 @@
#include <vcl/IDialogRenderable.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <tools/svborder.hxx>
#include <boost/property_tree/ptree.hpp>
#include <tools/json_writer.hxx>
#include <sal/log.hxx>

using namespace css;
@@ -194,15 +194,14 @@ void Deck::Resize()
 * Get the ordering as is shown in the layout, and our type as 'deck'
 * also elide nested panel windows.
 */
boost::property_tree::ptree Deck::DumpAsPropertyTree()
void Deck::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree;
    aTree.put("id", get_id());  // TODO could be missing - sort out
    aTree.put("type", "deck");
    aTree.put("text", GetText());
    aTree.put("enabled", IsEnabled());
    rJsonWriter.put("id", get_id());  // TODO could be missing - sort out
    rJsonWriter.put("type", "deck");
    rJsonWriter.put("text", GetText());
    rJsonWriter.put("enabled", IsEnabled());

    boost::property_tree::ptree aPanelNodes;
    auto childrenNode = rJsonWriter.startNode("children");
    for (auto &it : maPanels)
    {
        if (it->IsLurking())
@@ -216,21 +215,15 @@ boost::property_tree::ptree Deck::DumpAsPropertyTree()
        if (!pWindow)
            continue;

        boost::property_tree::ptree aPanel;
        aPanel.put("id", it->GetId());
        aPanel.put("type", "panel");
        aPanel.put("text", it->GetText());
        aPanel.put("enabled", it->IsEnabled());
        auto childNode = rJsonWriter.startNode("");
        rJsonWriter.put("id", it->GetId());
        rJsonWriter.put("type", "panel");
        rJsonWriter.put("text", it->GetText());
        rJsonWriter.put("enabled", it->IsEnabled());

        boost::property_tree::ptree aChildren;
        aChildren.push_back(std::make_pair("", pWindow->DumpAsPropertyTree()));
        aPanel.add_child("children", aChildren);

        aPanelNodes.push_back(std::make_pair("", aPanel));
        auto children2Node = rJsonWriter.startNode("children");
        pWindow->DumpAsPropertyTree(rJsonWriter);
    }
    aTree.add_child("children", aPanelNodes);

    return aTree;
}

bool Deck::ProcessWheelEvent(CommandEvent const * pCommandEvent)
diff --git a/sfx2/source/sidebar/Panel.cxx b/sfx2/source/sidebar/Panel.cxx
index 85b6ebf..6c7824b 100644
--- a/sfx2/source/sidebar/Panel.cxx
+++ b/sfx2/source/sidebar/Panel.cxx
@@ -25,6 +25,7 @@
#include <sfx2/sidebar/ResourceManager.hxx>

#include <sfx2/sidebar/SidebarController.hxx>
#include <tools/json_writer.hxx>


#ifdef DEBUG
@@ -37,8 +38,6 @@
#include <com/sun/star/ui/XSidebarPanel.hpp>
#include <com/sun/star/ui/XUIElement.hpp>

#include <boost/property_tree/ptree.hpp>

using namespace css;
using namespace css::uno;

@@ -83,16 +82,13 @@ void Panel::ApplySettings(vcl::RenderContext& rRenderContext)
    rRenderContext.SetBackground(Theme::GetPaint(Theme::Paint_PanelBackground).GetWallpaper());
}

boost::property_tree::ptree Panel::DumpAsPropertyTree()
void Panel::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    if (!IsLurking())
    {
        boost::property_tree::ptree aTree(vcl::Window::DumpAsPropertyTree());
        aTree.put("type", "panel");
        return aTree;
        vcl::Window::DumpAsPropertyTree(rJsonWriter);
        rJsonWriter.put("type", "panel");
    }
    else
        return boost::property_tree::ptree();
}

void Panel::dispose()
diff --git a/sfx2/source/sidebar/SidebarDockingWindow.cxx b/sfx2/source/sidebar/SidebarDockingWindow.cxx
index 7039983..8cc4200 100644
--- a/sfx2/source/sidebar/SidebarDockingWindow.cxx
+++ b/sfx2/source/sidebar/SidebarDockingWindow.cxx
@@ -29,6 +29,7 @@
#include <sfx2/viewfrm.hxx>
#include <svtools/acceleratorexecute.hxx>
#include <tools/gen.hxx>
#include <tools/json_writer.hxx>
#include <vcl/event.hxx>
#include <comphelper/lok.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -68,15 +69,15 @@ public:
            if (pMobileNotifier && pMobileNotifier->isLOKMobilePhone())
            {
                // Mobile phone.
                std::stringstream aStream;
                boost::property_tree::ptree aTree = m_rSidebarDockingWin.DumpAsPropertyTree();
                aTree.put("id", m_rSidebarDockingWin.GetLOKWindowId());
                boost::property_tree::write_json(aStream, aTree);
                const std::string message = aStream.str();
                tools::JsonWriter aJsonWriter;
                m_rSidebarDockingWin.DumpAsPropertyTree(aJsonWriter);
                aJsonWriter.put("id", m_rSidebarDockingWin.GetLOKWindowId());
                std::unique_ptr<char[]> data( aJsonWriter.extractData());
                std::string_view message(data.get());
                if (message != m_LastNotificationMessage)
                {
                    m_LastNotificationMessage = message;
                    pMobileNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str());
                    pMobileNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, m_LastNotificationMessage.c_str());
                }
            }

diff --git a/svx/source/sidebar/possize/PosSizePropertyPanel.cxx b/svx/source/sidebar/possize/PosSizePropertyPanel.cxx
index 248675f..322e670 100644
--- a/svx/source/sidebar/possize/PosSizePropertyPanel.cxx
+++ b/svx/source/sidebar/possize/PosSizePropertyPanel.cxx
@@ -853,14 +853,14 @@ void PosSizePropertyPanel::executeSize()
    }
}

boost::property_tree::ptree PosSizePropertyPanel::DumpAsPropertyTree()
void PosSizePropertyPanel::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    if (meDlgUnit != GetCurrentUnit(SfxItemState::DEFAULT, nullptr))
    {
        mpBindings->Update( SID_ATTR_METRIC );
    }

    return PanelLayout::DumpAsPropertyTree();
    PanelLayout::DumpAsPropertyTree(rJsonWriter);
}

void PosSizePropertyPanel::MetricState( SfxItemState eState, const SfxPoolItem* pState )
diff --git a/svx/source/sidebar/possize/PosSizePropertyPanel.hxx b/svx/source/sidebar/possize/PosSizePropertyPanel.hxx
index 8abd1e0..a35c8a4 100644
--- a/svx/source/sidebar/possize/PosSizePropertyPanel.hxx
+++ b/svx/source/sidebar/possize/PosSizePropertyPanel.hxx
@@ -66,7 +66,7 @@ public:
        const SfxItemState eState,
        const SfxPoolItem* pState) override;

    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;

    SfxBindings* GetBindings() { return mpBindings;}

diff --git a/svx/source/tbxctrls/fillctrl.cxx b/svx/source/tbxctrls/fillctrl.cxx
index 3d91e5c..fcdd67e 100644
--- a/svx/source/tbxctrls/fillctrl.cxx
+++ b/svx/source/tbxctrls/fillctrl.cxx
@@ -26,6 +26,7 @@
#include <vcl/settings.hxx>
#include <vcl/toolbox.hxx>
#include <svx/svxids.hrc>
#include <tools/json_writer.hxx>

#define TMP_STR_BEGIN   "["
#define TMP_STR_END     "]"
@@ -579,9 +580,9 @@ FillControl::FillControl(vcl::Window* pParent, const css::uno::Reference<css::fr
    SetOptimalSize();
}

IMPL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void)
IMPL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
{
    rTree.put("command", ".uno:FillStyle");
    rJsonWriter.put("command", ".uno:FillStyle");
}

void FillControl::ReleaseFocus_Impl()
diff --git a/svx/source/tbxctrls/tbcontrl.cxx b/svx/source/tbxctrls/tbcontrl.cxx
index 732ad7d..d8e0e6d 100644
--- a/svx/source/tbxctrls/tbcontrl.cxx
+++ b/svx/source/tbxctrls/tbcontrl.cxx
@@ -98,9 +98,9 @@
#include <bitmaps.hlst>
#include <sal/log.hxx>
#include <unotools/collatorwrapper.hxx>
#include <boost/property_tree/ptree.hpp>

#include <comphelper/lok.hxx>
#include <tools/json_writer.hxx>

#define MAX_MRU_FONTNAME_ENTRIES    5

@@ -194,7 +194,7 @@ private:
    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
    DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
    DECL_LINK(FocusOutHdl, weld::Widget&, void);
    DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void);
    DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void);
    DECL_LINK(CustomRenderHdl, weld::ComboBox::render_args, void);
    DECL_LINK(CustomGetSizeHdl, OutputDevice&, Size);

@@ -366,7 +366,7 @@ public:
    DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
    DECL_LINK(FocusInHdl, weld::Widget&, void);
    DECL_LINK(FocusOutHdl, weld::Widget&, void);
    DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void);
    DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void);
};

class SvxFontNameBox_Impl final : public InterimItemWindow
@@ -1342,33 +1342,30 @@ Color SvxStyleBox_Base::TestColorsVisible(const Color &FontCol, const Color &Bac
    return retCol;
}

IMPL_LINK(SvxStyleBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void)
IMPL_LINK(SvxStyleBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
{
    boost::property_tree::ptree aEntries;

    for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i)
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", m_xWidget->get_text(i));
        aEntries.push_back(std::make_pair("", aEntry));
        auto entriesNode = rJsonWriter.startNode("entries");
        for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i)
        {
            auto entryNode = rJsonWriter.startNode("");
            rJsonWriter.put("", m_xWidget->get_text(i));
        }
    }

    rTree.add_child("entries", aEntries);

    boost::property_tree::ptree aSelected;

    int nActive = m_xWidget->get_active();
    rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nActive == -1 ? 0 : 1));

    if (nActive != -1)
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", nActive);
        aSelected.push_back(std::make_pair("", aEntry));
        auto selectedNode = rJsonWriter.startNode("selectedEntries");
        if (nActive != -1)
        {
            auto node = rJsonWriter.startNode("");
            rJsonWriter.put("", static_cast<sal_Int32>(nActive));
        }
    }

    rTree.put("selectedCount", nActive == -1 ? 0 : 1);
    rTree.add_child("selectedEntries", aSelected);
    rTree.put("command", ".uno:StyleApply");
    rJsonWriter.put("command", ".uno:StyleApply");
}

static bool lcl_GetDocFontList(const FontList** ppFontList, SvxFontNameBox_Base* pBox)
@@ -1711,32 +1708,30 @@ void SvxFontNameBox_Base::Select(bool bNonTravelSelect)
    }
}

IMPL_LINK(SvxFontNameBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void)
IMPL_LINK(SvxFontNameBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
{
    boost::property_tree::ptree aEntries;

    for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i)
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", m_xWidget->get_text(i));
        aEntries.push_back(std::make_pair("", aEntry));
        auto entriesNode = rJsonWriter.startNode("entries");
        for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i)
        {
            auto entryNode = rJsonWriter.startNode("");
            rJsonWriter.put("", m_xWidget->get_text(i));
        }
    }

    rTree.add_child("entries", aEntries);

    boost::property_tree::ptree aSelected;

    int nSelectedEntry = m_xWidget->get_active();
    if (nSelectedEntry != -1)
    rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nSelectedEntry == -1 ? 0 : 1));

    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", m_xWidget->get_text(nSelectedEntry));
        aSelected.push_back(std::make_pair("", aEntry));
        auto selectedNode = rJsonWriter.startNode("selectedEntries");
        if (nSelectedEntry != -1)
        {
            auto entryNode = rJsonWriter.startNode("");
            rJsonWriter.put("", m_xWidget->get_text(nSelectedEntry));
        }
    }

    rTree.put("selectedCount", nSelectedEntry == -1 ? 0 : 1);
    rTree.add_child("selectedEntries", aSelected);
    rTree.put("command", ".uno:CharFontName");
    rJsonWriter.put("command", ".uno:CharFontName");
}

ColorWindow::ColorWindow(const OUString& rCommand,
diff --git a/svx/source/tbxctrls/tbunocontroller.cxx b/svx/source/tbxctrls/tbunocontroller.cxx
index 8e42177..f1d1db4 100644
--- a/svx/source/tbxctrls/tbunocontroller.cxx
+++ b/svx/source/tbxctrls/tbunocontroller.cxx
@@ -34,6 +34,7 @@
#include <svtools/ctrltool.hxx>
#include <svtools/ctrlbox.hxx>
#include <svtools/toolboxcontroller.hxx>
#include <tools/json_writer.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/supportsservice.hxx>

@@ -41,7 +42,6 @@

#include <vcl/InterimItemWindow.hxx>
#include <sfx2/sidebar/SidebarToolBox.hxx>
#include <boost/property_tree/ptree.hpp>

using namespace ::com::sun::star;

@@ -125,7 +125,7 @@ protected:
    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
    DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
    DECL_LINK(FocusOutHdl, weld::Widget&, void);
    DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void);
    DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void);
};

class SvxFontSizeBox_Impl final : public InterimItemWindow
@@ -337,33 +337,29 @@ void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
    }
}

IMPL_LINK(SvxFontSizeBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void)
IMPL_LINK(SvxFontSizeBox_Base, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
{
    boost::property_tree::ptree aEntries;

    for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i)
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", m_xWidget->get_text(i));
        aEntries.push_back(std::make_pair("", aEntry));
        auto entriesNode = rJsonWriter.startNode("entries");
        for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i)
        {
            auto entryNode = rJsonWriter.startNode("");
            rJsonWriter.put("", m_xWidget->get_text(i));
        }
    }

    rTree.add_child("entries", aEntries);

    boost::property_tree::ptree aSelected;

    int nActive = m_xWidget->get_active();
    if (nActive != -1)
    rJsonWriter.put("selectedCount", static_cast<sal_Int32>(nActive == -1 ? 0 : 1));
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", nActive);
        aSelected.push_back(std::make_pair("", aEntry));
        auto selectedNode = rJsonWriter.startNode("selectedEntries");
        if (nActive != -1)
        {
            auto node = rJsonWriter.startNode("");
            rJsonWriter.put("", static_cast<sal_Int32>(nActive));
        }
    }

    rTree.put("selectedCount", nActive == -1 ? 0 : 1);
    rTree.add_child("selectedEntries", aSelected);

    rTree.put("command", ".uno:FontHeight");
    rJsonWriter.put("command", ".uno:FontHeight");
}

FontHeightToolBoxControl::FontHeightToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext )
diff --git a/sw/source/uibase/app/swmodul1.cxx b/sw/source/uibase/app/swmodul1.cxx
index cbaf3bd..abe620c 100644
--- a/sw/source/uibase/app/swmodul1.cxx
+++ b/sw/source/uibase/app/swmodul1.cxx
@@ -440,7 +440,7 @@ void SwModule::GetRedlineAuthorInfo(tools::JsonWriter& rJsonWriter)
    for (std::size_t nAuthor = 0; nAuthor < m_pAuthorNames.size(); ++nAuthor)
    {
        auto authorNode = rJsonWriter.startNode("");
        rJsonWriter.put("index", nAuthor);
        rJsonWriter.put("index", static_cast<sal_Int64>(nAuthor));
        rJsonWriter.put("name", m_pAuthorNames[nAuthor]);
        rJsonWriter.put("color", sal_uInt32(lcl_GetAuthorColor(nAuthor)));
    }
diff --git a/tools/qa/cppunit/test_json_writer.cxx b/tools/qa/cppunit/test_json_writer.cxx
index 6d473e6..d5c0378 100644
--- a/tools/qa/cppunit/test_json_writer.cxx
+++ b/tools/qa/cppunit/test_json_writer.cxx
@@ -48,7 +48,7 @@ void JsonWriterTest::test1()
        aJson.put("oustring", OUString("val1"));
        aJson.put("ostring", OString("val2"));
        aJson.put("charptr", "val3");
        aJson.put("int", 12);
        aJson.put("int", static_cast<sal_Int32>(12));
    }

    std::unique_ptr<char, o3tl::free_delete> result(aJson.extractData());
diff --git a/tools/source/misc/json_writer.cxx b/tools/source/misc/json_writer.cxx
index be891ef..aacf3f7 100644
--- a/tools/source/misc/json_writer.cxx
+++ b/tools/source/misc/json_writer.cxx
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <cstring>
#include <rtl/strbuf.hxx>
#include <rtl/math.hxx>

namespace tools
{
@@ -270,7 +271,7 @@ void JsonWriter::put(const char* pPropName, const char* pPropVal)
    ++mPos;
}

void JsonWriter::put(const char* pPropName, int nPropVal)
void JsonWriter::put(const char* pPropName, sal_Int64 nPropVal)
{
    auto nPropNameLength = strlen(pPropName);
    auto nWorstCasePropValLength = 32;
@@ -285,7 +286,49 @@ void JsonWriter::put(const char* pPropName, int nPropVal)
    memcpy(mPos, "\": ", 3);
    mPos += 3;

    mPos += sprintf(mPos, "%d", nPropVal);
    mPos += sprintf(mPos, "%ld", nPropVal);
}

void JsonWriter::put(const char* pPropName, double fPropVal)
{
    OString sPropVal = rtl::math::doubleToString(fPropVal, rtl_math_StringFormat_F, 12, '.');
    auto nPropNameLength = strlen(pPropName);
    ensureSpace(nPropNameLength + sPropVal.getLength() + 8);

    addCommaBeforeField();

    *mPos = '"';
    ++mPos;
    memcpy(mPos, pPropName, nPropNameLength);
    mPos += nPropNameLength;
    memcpy(mPos, "\": ", 3);
    mPos += 3;

    memcpy(mPos, sPropVal.getStr(), sPropVal.getLength());
    mPos += sPropVal.getLength();
}

void JsonWriter::put(const char* pPropName, bool nPropVal)
{
    auto nPropNameLength = strlen(pPropName);
    ensureSpace(nPropNameLength + 5 + 8);

    addCommaBeforeField();

    *mPos = '"';
    ++mPos;
    memcpy(mPos, pPropName, nPropNameLength);
    mPos += nPropNameLength;
    memcpy(mPos, "\": ", 3);
    mPos += 3;

    const char* pVal;
    if (nPropVal)
        pVal = "true";
    else
        pVal = "false";
    memcpy(mPos, pVal, strlen(pVal));
    mPos += strlen(pVal);
}

void JsonWriter::putRaw(const rtl::OStringBuffer& rRawBuf)
@@ -349,5 +392,19 @@ OString JsonWriter::extractAsOString()
    return ret;
}

std::string JsonWriter::extractAsStdString()
{
    char* pChar = extractData();
    std::string ret(pChar);
    free(pChar);
    return ret;
}

bool JsonWriter::isDataEquals(const std::string& s)
{
    return s.length() == static_cast<size_t>(mPos - mpBuffer)
           && memcmp(s.data(), mpBuffer, s.length()) == 0;
}

} // namespace tools
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx
index f1fbb41..3e748bf 100644
--- a/vcl/inc/salvtables.hxx
+++ b/vcl/inc/salvtables.hxx
@@ -377,8 +377,7 @@ public:

    virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() override;

    virtual void
    connect_get_property_tree(const Link<boost::property_tree::ptree&, void>& rLink) override;
    virtual void connect_get_property_tree(const Link<tools::JsonWriter&, void>& rLink) override;

    virtual void set_stack_background() override;

diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index 6b362e7..8533f8b 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -249,7 +249,7 @@ public:
    std::set<Link<VclWindowEvent&,void>> maChildEventListenersDeleted;
    Link<vcl::Window&, bool> maHelpRequestHdl;
    Link<vcl::Window&, bool> maMnemonicActivateHdl;
    Link<boost::property_tree::ptree&, void> maDumpAsPropertyTreeHdl;
    Link<tools::JsonWriter&, void> maDumpAsPropertyTreeHdl;

    // The canvas interface for this VCL window. Is persistent after the first GetCanvas() call
    css::uno::WeakReference< css::rendering::XCanvas >    mxCanvas;
diff --git a/vcl/jsdialog/jsdialogbuilder.cxx b/vcl/jsdialog/jsdialogbuilder.cxx
index fa7f25d..e27bc81 100644
--- a/vcl/jsdialog/jsdialogbuilder.cxx
+++ b/vcl/jsdialog/jsdialogbuilder.cxx
@@ -9,13 +9,15 @@

#include <jsdialog/jsdialogbuilder.hxx>
#include <sal/log.hxx>
#include <boost/property_tree/json_parser.hpp>
#include <comphelper/lok.hxx>
#include <vcl/tabpage.hxx>
#include <vcl/toolkit/dialog.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <vcl/toolkit/combobox.hxx>
#include <messagedialog.hxx>
#include <tools/json_writer.hxx>
#include <o3tl/deleter.hxx>
#include <memory>

JSDialogNotifyIdle::JSDialogNotifyIdle(VclPtr<vcl::Window> aWindow)
    : Idle("JSDialog notify")
@@ -35,15 +37,14 @@ void JSDialogNotifyIdle::Invoke()
        const vcl::ILibreOfficeKitNotifier* pNotifier = m_aWindow->GetLOKNotifier();
        if (pNotifier)
        {
            std::stringstream aStream;
            boost::property_tree::ptree aTree = m_aWindow->DumpAsPropertyTree();
            aTree.put("id", m_aWindow->GetLOKWindowId());
            boost::property_tree::write_json(aStream, aTree);
            const std::string message = aStream.str();
            if (message != m_LastNotificationMessage)
            tools::JsonWriter aJsonWriter;
            m_aWindow->DumpAsPropertyTree(aJsonWriter);
            aJsonWriter.put("id", m_aWindow->GetLOKWindowId());
            if (!aJsonWriter.isDataEquals(m_LastNotificationMessage))
            {
                m_LastNotificationMessage = message;
                pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str());
                m_LastNotificationMessage = aJsonWriter.extractAsStdString();
                pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG,
                                                      m_LastNotificationMessage.c_str());
            }
        }
    }
@@ -143,12 +144,10 @@ std::unique_ptr<weld::Dialog> JSInstanceBuilder::weld_dialog(const OString& id, 
    const vcl::ILibreOfficeKitNotifier* pNotifier = pDialog->GetLOKNotifier();
    if (pNotifier)
    {
        std::stringstream aStream;
        boost::property_tree::ptree aTree = m_aOwnedToplevel->DumpAsPropertyTree();
        aTree.put("id", m_aOwnedToplevel->GetLOKWindowId());
        boost::property_tree::write_json(aStream, aTree);
        const std::string message = aStream.str();
        pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str());
        tools::JsonWriter aJsonWriter;
        m_aOwnedToplevel->DumpAsPropertyTree(aJsonWriter);
        aJsonWriter.put("id", m_aOwnedToplevel->GetLOKWindowId());
        pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, aJsonWriter.extractData());
    }

    return pRet;
@@ -280,12 +279,11 @@ weld::MessageDialog* JSInstanceBuilder::CreateMessageDialog(weld::Widget* pParen
    const vcl::ILibreOfficeKitNotifier* pNotifier = xMessageDialog->GetLOKNotifier();
    if (pNotifier)
    {
        std::stringstream aStream;
        boost::property_tree::ptree aTree = xMessageDialog->DumpAsPropertyTree();
        aTree.put("id", xMessageDialog->GetLOKWindowId());
        boost::property_tree::write_json(aStream, aTree);
        const std::string message = aStream.str();
        pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.c_str());
        tools::JsonWriter aJsonWriter;
        xMessageDialog->DumpAsPropertyTree(aJsonWriter);
        aJsonWriter.put("id", xMessageDialog->GetLOKWindowId());
        std::unique_ptr<char[], o3tl::free_delete> message(aJsonWriter.extractData());
        pNotifier->libreOfficeKitViewCallback(LOK_CALLBACK_JSDIALOG, message.get());
    }

    return new JSMessageDialog(xMessageDialog, nullptr, true);
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 9a94843..f395d52 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -501,7 +501,7 @@ css::uno::Reference<css::datatransfer::dnd::XDropTarget> SalInstanceWidget::get_
}

void SalInstanceWidget::connect_get_property_tree(
    const Link<boost::property_tree::ptree&, void>& rLink)
    const Link<tools::JsonWriter&, void>& rLink)
{
    m_xWidget->SetDumpAsPropertyTreeHdl(rLink);
}
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index afc27c1..05e8aa4 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -45,6 +45,7 @@
#include <comphelper/lok.hxx>
#include <officecfg/Office/Common.hxx>
#include <boost/property_tree/ptree.hpp>
#include <tools/json_writer.hxx>


using namespace css;
@@ -552,11 +553,10 @@ FactoryFunction Button::GetUITestFactory() const
    return ButtonUIObject::create;
}

boost::property_tree::ptree Button::DumpAsPropertyTree()
void Button::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(Control::DumpAsPropertyTree());
    aTree.put("text", GetText());
    return aTree;
    Control::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("text", GetText());
}

IMPL_STATIC_LINK( Button, dispatchCommandHandler, Button*, pButton, void )
@@ -2844,11 +2844,10 @@ void RadioButton::ShowFocus(const tools::Rectangle& rRect)
    Button::ShowFocus(rRect);
}

boost::property_tree::ptree RadioButton::DumpAsPropertyTree()
void RadioButton::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(Button::DumpAsPropertyTree());
    aTree.put("checked", IsChecked());
    return aTree;
    Button::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("checked", IsChecked());
}

FactoryFunction RadioButton::GetUITestFactory() const
@@ -3661,11 +3660,10 @@ void CheckBox::ShowFocus(const tools::Rectangle& rRect)
    Button::ShowFocus(rRect);
}

boost::property_tree::ptree CheckBox::DumpAsPropertyTree()
void CheckBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(Button::DumpAsPropertyTree());
    aTree.put("checked", IsChecked());
    return aTree;
    Button::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("checked", IsChecked());
}

FactoryFunction CheckBox::GetUITestFactory() const
diff --git a/vcl/source/control/field.cxx b/vcl/source/control/field.cxx
index d81c3b3..e7a6472 100644
--- a/vcl/source/control/field.cxx
+++ b/vcl/source/control/field.cxx
@@ -43,6 +43,7 @@

#include <unotools/localedatawrapper.hxx>
#include <boost/property_tree/ptree.hpp>
#include <tools/json_writer.hxx>

using namespace ::com::sun::star;
using namespace ::comphelper;
@@ -871,12 +872,11 @@ void NumericField::Last()
    SpinField::Last();
}

boost::property_tree::ptree NumericField::DumpAsPropertyTree()
void NumericField::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
    aTree.put("min", GetMin());
    aTree.put("max", GetMax());
    return aTree;
    SpinField::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("min", GetMin());
    rJsonWriter.put("max", GetMax());
}

namespace
@@ -1712,17 +1712,15 @@ void MetricField::Last()
    SpinField::Last();
}

boost::property_tree::ptree MetricField::DumpAsPropertyTree()
void MetricField::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
    aTree.put("min", GetMin());
    aTree.put("max", GetMax());
    aTree.put("unit", FieldUnitToString(GetUnit()));
    SpinField::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("min", GetMin());
    rJsonWriter.put("max", GetMax());
    rJsonWriter.put("unit", FieldUnitToString(GetUnit()));
    OUString sValue = Application::GetSettings().GetNeutralLocaleDataWrapper().
        getNum(GetValue(), GetDecimalDigits(), false, false);
    aTree.put("value", sValue.toUtf8().getStr());

    return aTree;
    rJsonWriter.put("value", sValue);
}

FactoryFunction MetricField::GetUITestFactory() const
diff --git a/vcl/source/control/fmtfield.cxx b/vcl/source/control/fmtfield.cxx
index 87ff8b7..c00a721 100644
--- a/vcl/source/control/fmtfield.cxx
+++ b/vcl/source/control/fmtfield.cxx
@@ -38,6 +38,7 @@
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <osl/diagnose.h>
#include <tools/json_writer.hxx>

using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;
@@ -1091,17 +1092,12 @@ void FormattedField::UseInputStringForFormatting()
    m_bUseInputStringForFormatting = true;
}

boost::property_tree::ptree FormattedField::DumpAsPropertyTree()
void FormattedField::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(SpinField::DumpAsPropertyTree());
    aTree.put("min", rtl::math::doubleToString(GetMinValue(),
        rtl_math_StringFormat_F, GetDecimalDigits(), '.').getStr());
    aTree.put("max", rtl::math::doubleToString(GetMaxValue(),
        rtl_math_StringFormat_F, GetDecimalDigits(), '.').getStr());
    aTree.put("value", rtl::math::doubleToString(GetValue(),
        rtl_math_StringFormat_F, GetDecimalDigits(), '.').getStr());

    return aTree;
    SpinField::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("min", GetMinValue());
    rJsonWriter.put("max", GetMaxValue());
    rJsonWriter.put("value", GetValue());
}

FactoryFunction FormattedField::GetUITestFactory() const
diff --git a/vcl/source/control/listbox.cxx b/vcl/source/control/listbox.cxx
index 9b3cb51..fc7806d 100644
--- a/vcl/source/control/listbox.cxx
+++ b/vcl/source/control/listbox.cxx
@@ -33,6 +33,7 @@

#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
#include <boost/property_tree/ptree.hpp>
#include <tools/json_writer.hxx>

ListBox::ListBox(WindowType nType)
    : Control(nType)
@@ -1394,33 +1395,29 @@ FactoryFunction ListBox::GetUITestFactory() const
    return ListBoxUIObject::create;
}

boost::property_tree::ptree ListBox::DumpAsPropertyTree()
void ListBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(Control::DumpAsPropertyTree());
    boost::property_tree::ptree aEntries;
    Control::DumpAsPropertyTree(rJsonWriter);

    for (int i = 0; i < GetEntryCount(); ++i)
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", GetEntry(i));
        aEntries.push_back(std::make_pair("", aEntry));
        auto entriesNode = rJsonWriter.startNode("entries");
        for (int i = 0; i < GetEntryCount(); ++i)
        {
            auto entryNode = rJsonWriter.startNode("");
            rJsonWriter.put("", GetEntry(i));
        }
    }

    aTree.add_child("entries", aEntries);
    rJsonWriter.put("selectedCount", GetSelectedEntryCount());

    boost::property_tree::ptree aSelected;

    for (int i = 0; i < GetSelectedEntryCount(); ++i)
    {
        boost::property_tree::ptree aEntry;
        aEntry.put("", GetSelectedEntryPos(i));
        aSelected.push_back(std::make_pair("", aEntry));
        auto entriesNode = rJsonWriter.startNode("selectedEntries");
        for (int i = 0; i < GetSelectedEntryCount(); ++i)
        {
            auto entryNode = rJsonWriter.startNode("");
            rJsonWriter.put("", GetSelectedEntryPos(i));
        }
    }

    aTree.put("selectedCount", GetSelectedEntryCount());
    aTree.add_child("selectedEntries", aSelected);

    return aTree;
}

MultiListBox::MultiListBox( vcl::Window* pParent, WinBits nStyle ) :
diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx
index 0afb000..728e4c3 100644
--- a/vcl/source/control/tabctrl.cxx
+++ b/vcl/source/control/tabctrl.cxx
@@ -34,6 +34,7 @@
#include <vcl/settings.hxx>
#include <vcl/uitest/uiobject.hxx>
#include <bitmaps.hlst>
#include <tools/json_writer.hxx>

#include <controldata.hxx>
#include <svdata.hxx>
@@ -2160,24 +2161,20 @@ FactoryFunction TabControl::GetUITestFactory() const
    return TabControlUIObject::create;
}

boost::property_tree::ptree TabControl::DumpAsPropertyTree()
void TabControl::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree = Control::DumpAsPropertyTree();

    boost::property_tree::ptree aTabs;
    for(auto id : GetPageIDs())
    Control::DumpAsPropertyTree(rJsonWriter);
    {
        boost::property_tree::ptree aTab;
        aTab.put("text", GetPageText(id));
        aTab.put("id", id);
        aTab.put("name", GetPageName(id));
        aTabs.push_back(std::make_pair("", aTab));
        auto tabsNode = rJsonWriter.startNode("tabs");
        for(auto id : GetPageIDs())
        {
            auto tabNode = rJsonWriter.startNode("");
            rJsonWriter.put("text", GetPageText(id));
            rJsonWriter.put("id", id);
            rJsonWriter.put("name", GetPageName(id));
        }
    }

    aTree.add_child("tabs", aTabs);
    aTree.put("selected", GetCurPageId());

    return aTree;
    rJsonWriter.put("selected", GetCurPageId());
}

sal_uInt16 NotebookbarTabControlBase::m_nHeaderHeight = 0;
diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx
index af7208c..f09563f 100644
--- a/vcl/source/window/layout.cxx
+++ b/vcl/source/window/layout.cxx
@@ -27,6 +27,7 @@
#include <boost/property_tree/ptree.hpp>
#include <vcl/vclmedit.hxx>
#include <sal/log.hxx>
#include <tools/json_writer.hxx>

VclContainer::VclContainer(vcl::Window *pParent, WinBits nStyle)
    : Window(WindowType::CONTAINER)
@@ -360,11 +361,10 @@ bool VclBox::set_property(const OString &rKey, const OUString &rValue)
    return true;
}

boost::property_tree::ptree VclBox::DumpAsPropertyTree()
void VclBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(VclContainer::DumpAsPropertyTree());
    aTree.put("vertical", m_bVerticalContainer);
    return aTree;
    VclContainer::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("vertical", m_bVerticalContainer);
}

sal_uInt16 VclBox::getDefaultAccessibleRole() const
@@ -1308,11 +1308,10 @@ void VclGrid::setAllocation(const Size& rAllocation)
    }
}

boost::property_tree::ptree VclGrid::DumpAsPropertyTree()
void VclGrid::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(VclContainer::DumpAsPropertyTree());
    aTree.put("type", "grid");
    return aTree;
    VclContainer::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("type", "grid");
}

bool toBool(const OUString &rValue)
@@ -1493,11 +1492,10 @@ OUString VclFrame::getDefaultAccessibleName() const
    return VclBin::getDefaultAccessibleName();
}

boost::property_tree::ptree VclFrame::DumpAsPropertyTree()
void VclFrame::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(VclBin::DumpAsPropertyTree());
    aTree.put("type", "frame");
    return aTree;
    VclBin::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("type", "frame");
}

Size VclAlignment::calculateRequisition() const
@@ -2855,25 +2853,24 @@ VclScrolledWindow::~VclScrolledWindow()
    disposeOnce();
}

boost::property_tree::ptree VclDrawingArea::DumpAsPropertyTree()
void VclDrawingArea::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(Control::DumpAsPropertyTree());
    aTree.put("type", "drawingarea");
    Control::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("type", "drawingarea");

    ScopedVclPtrInstance<VirtualDevice> pDevice;
    pDevice->SetOutputSize( GetSizePixel() );
    tools::Rectangle aRect(Point(0,0), GetSizePixel());
    Paint(*pDevice, aRect);
    BitmapEx aImage = pDevice->GetBitmapEx( Point(0,0), GetSizePixel() );
    SvMemoryStream aOStm(65535, 65535);

    if(GraphicConverter::Export(aOStm, aImage, ConvertDataFormat::PNG) == ERRCODE_NONE)
    {
        css::uno::Sequence<sal_Int8> aSeq( static_cast<sal_Int8 const *>(aOStm.GetData()), aOStm.Tell());
        OUStringBuffer aBuffer("data:image/png;base64,");
        ::comphelper::Base64::encode(aBuffer, aSeq);
        aTree.put("image", aBuffer.makeStringAndClear());
        rJsonWriter.put("image", aBuffer.makeStringAndClear());
    }
    return aTree;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
index 3d1bcd7..6ee94e7 100644
--- a/vcl/source/window/toolbox2.cxx
+++ b/vcl/source/window/toolbox2.cxx
@@ -39,6 +39,7 @@
#include <toolbox.h>

#include <unotools/confignode.hxx>
#include <tools/json_writer.hxx>

using namespace vcl;

@@ -1745,34 +1746,25 @@ void ToolBox::WillUsePopupMode( bool b )
    mpData->mbWillUsePopupMode = b;
}

boost::property_tree::ptree ToolBox::DumpAsPropertyTree()
void ToolBox::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    boost::property_tree::ptree aTree(DockingWindow::DumpAsPropertyTree());
    boost::property_tree::ptree aChildren;
    DockingWindow::DumpAsPropertyTree(rJsonWriter);

    boost::property_tree::ptree::const_assoc_iterator found = aTree.find("children");
    if (found == aTree.not_found())
    auto childrenNode = rJsonWriter.startNode("children");
    for (ToolBox::ImplToolItems::size_type i = 0; i < GetItemCount(); ++i)
    {
        for (ToolBox::ImplToolItems::size_type i = 0; i < GetItemCount(); ++i)
        ToolBoxItemType type = GetItemType(i);
        if (type == ToolBoxItemType::BUTTON)
        {
            ToolBoxItemType type = GetItemType(i);
            if (type == ToolBoxItemType::BUTTON)
            {
                boost::property_tree::ptree aEntry;
                int nId = GetItemId(i);
                if (!IsItemVisible(nId))
                    continue;
                aEntry.put("type", "toolitem");
                aEntry.put("text", GetItemText(nId));
                aEntry.put("command", GetItemCommand(nId));
                aChildren.push_back(std::make_pair("", aEntry));
            }
            auto childNode = rJsonWriter.startNode("");
            int nId = GetItemId(i);
            if (!IsItemVisible(nId))
                continue;
            rJsonWriter.put("type", "toolitem");
            rJsonWriter.put("text", GetItemText(nId));
            rJsonWriter.put("command", GetItemCommand(nId));
        }

        aTree.add_child("children", aChildren);
    }

    return aTree;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index c3baf5e6..e1c498d 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -68,6 +68,7 @@
#include <unotools/configmgr.hxx>
#include <osl/diagnose.h>
#include <tools/debug.hxx>
#include <tools/json_writer.hxx>
#include <boost/property_tree/ptree.hpp>

#include <cassert>
@@ -1768,7 +1769,7 @@ void Window::ImplNewInputContext()
    pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
}

void Window::SetDumpAsPropertyTreeHdl(const Link<boost::property_tree::ptree&, void>& rLink)
void Window::SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink)
{
    if (mpWindowImpl) // may be called after dispose
    {
@@ -3380,47 +3381,34 @@ const char* windowTypeName(WindowType nWindowType)

}

boost::property_tree::ptree Window::DumpAsPropertyTree()
void Window::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    // This is for the code in sc/source/ui/sidebar/AlignmentPropertyPanel.cxx.
    // Also see commit f27c6320e8496d690b5d341d3718430709263a1c
    // "lok: remove complex rotation / alignment settings"
    if (get_id() == "textorientbox") {
        return boost::property_tree::ptree();
    }
    rJsonWriter.put("id", get_id());  // TODO could be missing - sort out
    rJsonWriter.put("type", windowTypeName(GetType()));
    rJsonWriter.put("text", GetText());
    rJsonWriter.put("enabled", IsEnabled());

    boost::property_tree::ptree aTree;
    aTree.put("id", get_id());  // TODO could be missing - sort out
    aTree.put("type", windowTypeName(GetType()));
    aTree.put("text", GetText());
    aTree.put("enabled", IsEnabled());

    boost::property_tree::ptree aChildren;
    if (vcl::Window* pChild = mpWindowImpl->mpFirstChild)
    {
        auto childrenNode = rJsonWriter.startNode("children");
        while (pChild)
        {
            if (pChild->IsVisible()) {
                boost::property_tree::ptree aSubTree = pChild->DumpAsPropertyTree();
                int nLeft = pChild->get_grid_left_attach();
                int nTop = pChild->get_grid_top_attach();
                auto childNode = rJsonWriter.startNode("");
                pChild->DumpAsPropertyTree(rJsonWriter);
                sal_Int32 nLeft = pChild->get_grid_left_attach();
                sal_Int32 nTop = pChild->get_grid_top_attach();
                if (nLeft != -1 && nTop != -1)
                {
                    OUString sLeft = OUString::number(nLeft);
                    OUString sTop = OUString::number(nTop);
                    aSubTree.put("left", sLeft);
                    aSubTree.put("top", sTop);
                    rJsonWriter.put("left", nLeft);
                    rJsonWriter.put("top", nTop);
                }
                aChildren.push_back(std::make_pair("", aSubTree));
            }
            pChild = pChild->mpWindowImpl->mpNext;
        }
        aTree.add_child("children", aChildren);
    }

    mpWindowImpl->maDumpAsPropertyTreeHdl.Call(aTree);

    return aTree;
    mpWindowImpl->maDumpAsPropertyTreeHdl.Call(rJsonWriter);
}

void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index c38e1eb..7270e3e 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -2906,7 +2906,7 @@ public:
        return m_xDropTarget.get();
    }

    virtual void connect_get_property_tree(const Link<boost::property_tree::ptree&, void>& /*rLink*/) override
    virtual void connect_get_property_tree(const Link<tools::JsonWriter&, void>& /*rLink*/) override
    {
        //not implemented for the gtk variant
    }