[Libreoffice-commits] core.git: cui/inc cui/Library_cui.mk cui/source cui/uiconfig cui/UIConfig_cui.mk include/sfx2 include/vcl officecfg/registry sc/sdi sc/source sd/sdi sd/source sfx2/sdi sw/sdi sw/source

Yusuf Keten (via logerrit) logerrit at kemper.freedesktop.org
Thu Jun 25 20:17:30 UTC 2020


 cui/Library_cui.mk                                                   |    1 
 cui/UIConfig_cui.mk                                                  |    2 
 cui/inc/strings.hrc                                                  |    4 
 cui/source/dialogs/AdditionsDialog.cxx                               |  260 +++++++++
 cui/source/factory/dlgfact.cxx                                       |   12 
 cui/source/factory/dlgfact.hxx                                       |   17 
 cui/source/inc/AdditionsDialog.hxx                                   |   71 ++
 cui/uiconfig/ui/additionsdialog.ui                                   |  183 ++++++
 cui/uiconfig/ui/additionsfragment.ui                                 |  277 ++++++++++
 include/sfx2/sfxsids.hrc                                             |    1 
 include/vcl/abstdlg.hxx                                              |   10 
 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu |   17 
 sc/sdi/tabvwsh.sdi                                                   |    1 
 sc/source/ui/view/tabvwshb.cxx                                       |    9 
 sd/sdi/_drvwsh.sdi                                                   |    5 
 sd/source/ui/view/drviews2.cxx                                       |   11 
 sfx2/sdi/docslots.sdi                                                |    5 
 sfx2/sdi/sfx.sdi                                                     |   17 
 sw/sdi/viewsh.sdi                                                    |    6 
 sw/source/uibase/uiview/viewdlg2.cxx                                 |    8 
 20 files changed, 917 insertions(+)

New commits:
commit 12bbcce5018a09f1ab4c629bdab813f9bf079605
Author:     Yusuf Keten <ketenyusuf at gmail.com>
AuthorDate: Fri Jun 5 14:50:39 2020 +0300
Commit:     Muhammet Kara <muhammet.kara at collabora.com>
CommitDate: Thu Jun 25 22:16:55 2020 +0200

    tdf#133026: Tight integration of extensions - Additions Dialog first iteration
    
    - Add the uno command .uno:AdditionsDialog
    - Add the necessary commands to cui makefiles.
    - Add the dialog AdditionsDialog for only test
    - Implement the basic functionality to show up when clicked on the
      menu/toolbar item.
    
    Change-Id: I89dd74e49f5ff246ca355d2f8d1397621b26dea6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95593
    Tested-by: Jenkins
    Reviewed-by: Muhammet Kara <muhammet.kara at collabora.com>

diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk
index 27d89ec1c3b6..ed1e07d5ff13 100644
--- a/cui/Library_cui.mk
+++ b/cui/Library_cui.mk
@@ -104,6 +104,7 @@ $(eval $(call gb_Library_add_exception_objects,cui,\
     cui/source/customize/SvxNotebookbarConfigPage \
     cui/source/customize/CustomNotebookbarGenerator \
     cui/source/dialogs/about \
+    cui/source/dialogs/AdditionsDialog \
     cui/source/dialogs/colorpicker \
     cui/source/dialogs/cuicharmap \
     cui/source/dialogs/cuifmsearch \
diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk
index ca8911310c2c..62291eff5acf 100644
--- a/cui/UIConfig_cui.mk
+++ b/cui/UIConfig_cui.mk
@@ -14,6 +14,8 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\
 	cui/uiconfig/ui/aboutconfigdialog\
 	cui/uiconfig/ui/aboutconfigvaluedialog \
 	cui/uiconfig/ui/accelconfigpage \
+	cui/uiconfig/ui/additionsdialog \
+	cui/uiconfig/ui/additionsfragment \
 	cui/uiconfig/ui/agingdialog \
 	cui/uiconfig/ui/acorexceptpage \
 	cui/uiconfig/ui/acoroptionspage \
diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc
index dcfbcc0f4e9c..20ec52202bc0 100644
--- a/cui/inc/strings.hrc
+++ b/cui/inc/strings.hrc
@@ -391,6 +391,10 @@
 #define RID_SVXSTR_DELETEUSERCOLOR1                 NC_("RID_SVXSTR_DELETEUSERCOLOR1", "You can only delete user-defined colors")
 #define RID_SVXSTR_DELETEUSERCOLOR2                 NC_("RID_SVXSTR_DELETEUSERCOLOR2", "Please select the color to delete")
 
+#define RID_SVXSTR_ADDITIONS_INSTALLBUTTON          NC_("RID_SVXSTR_ADDITIONS_INSTALLBUTTON", "Install")
+#define RID_SVXSTR_ADDITIONS_LICENCE                NC_("RID_SVXSTR_ADDITIONS_LICENCE", "License:")
+#define RID_SVXSTR_ADDITIONS_REQUIREDVERSION        NC_("RID_SVXSTR_ADDITIONS_REQUIREDVERSION","Required version: >=")
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/dialogs/AdditionsDialog.cxx b/cui/source/dialogs/AdditionsDialog.cxx
new file mode 100644
index 000000000000..5ed8ad97e46c
--- /dev/null
+++ b/cui/source/dialogs/AdditionsDialog.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <AdditionsDialog.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <unordered_set>
+#include <sal/log.hxx>
+#include <tools/stream.hxx>
+#include <strings.hrc>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/inspection/PropertyLineElement.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <dialmgr.hxx>
+
+#include <curl/curl.h>
+#include <orcus/json_document_tree.hpp>
+#include <orcus/config.hpp>
+#include <orcus/pstring.hpp>
+
+using namespace css;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::XComponentContext;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::graphic::GraphicProvider;
+using ::com::sun::star::graphic::XGraphicProvider;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::graphic::XGraphic;
+
+namespace
+{
+struct AdditionInfo
+{
+    OUString sName;
+    OUString sAuthorName;
+    OUString sPreviewURL;
+    OUString sScreenshotURL;
+    OUString sIntroduction;
+    OUString sDescription;
+    OUString sCompatibleVersion;
+    OUString sReleaseVersion;
+    OUString sLicense;
+    OUString sCommentNumber;
+    OUString sCommentURL;
+    OUString sRating;
+    OUString sDownloadNumber;
+    OUString sDownloadURL;
+};
+
+size_t WriteCallback(void* ptr, size_t size, size_t nmemb, void* userp)
+{
+    if (!userp)
+        return 0;
+
+    std::string* response = static_cast<std::string*>(userp);
+    size_t real_size = size * nmemb;
+    response->append(static_cast<char*>(ptr), real_size);
+    return real_size;
+}
+
+// Gets the content of the given URL and returns as a standard string
+std::string curlGet(const OString& rURL)
+{
+    CURL* curl = curl_easy_init();
+
+    if (!curl)
+        return std::string();
+
+    curl_easy_setopt(curl, CURLOPT_URL, rURL.getStr());
+
+    std::string response_body;
+
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(&response_body));
+
+    CURLcode cc = curl_easy_perform(curl);
+    long http_code = 0;
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
+
+    if (http_code != 200)
+    {
+        SAL_WARN("cui.dialogs", "Download failed. Error code: " << http_code);
+    }
+
+    if (cc != CURLE_OK)
+    {
+        SAL_WARN("cui.dialogs", "curl error: " << cc);
+    }
+
+    return response_body;
+}
+
+void parseResponse(const std::string& rResponse, std::vector<AdditionInfo>& aAdditions)
+{
+    orcus::json::document_tree aJsonDoc;
+    orcus::json_config aConfig;
+
+    if (rResponse.empty())
+        return;
+
+    aJsonDoc.load(rResponse, aConfig);
+
+    auto aDocumentRoot = aJsonDoc.get_document_root();
+    if (aDocumentRoot.type() != orcus::json::node_t::object)
+    {
+        SAL_WARN("cui.dialogs", "invalid root entries: " << rResponse);
+        return;
+    }
+
+    auto resultsArray = aDocumentRoot.child("extension");
+
+    for (size_t i = 0; i < resultsArray.child_count(); ++i)
+    {
+        auto arrayElement = resultsArray.child(i);
+
+        try
+        {
+            AdditionInfo aNewAddition = {
+                OStringToOUString(OString(arrayElement.child("name").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("author").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("URL").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("screenshotURL").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(
+                    OString(arrayElement.child("extensionIntroduction").string_value().get()),
+                    RTL_TEXTENCODING_UTF8),
+                OStringToOUString(
+                    OString(arrayElement.child("extensionDescription").string_value().get()),
+                    RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("releases")
+                                              .child(0)
+                                              .child("compatibleVersion")
+                                              .string_value()
+                                              .get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("releases")
+                                              .child(0)
+                                              .child("releaseNumber")
+                                              .string_value()
+                                              .get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("releases")
+                                              .child(0)
+                                              .child("license")
+                                              .string_value()
+                                              .get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("commentNumber").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("commentURL").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("rating").string_value().get()),
+                                  RTL_TEXTENCODING_UTF8),
+                OStringToOUString(
+                    OString(arrayElement.child("downloadNumber").string_value().get()),
+                    RTL_TEXTENCODING_UTF8),
+                OStringToOUString(OString(arrayElement.child("releases")
+                                              .child(0)
+                                              .child("downloadURL")
+                                              .string_value()
+                                              .get()),
+                                  RTL_TEXTENCODING_UTF8)
+            };
+
+            aAdditions.push_back(aNewAddition);
+        }
+        catch (orcus::json::document_error& e)
+        {
+            // This usually happens when one of the values is null (type() == orcus::json::node_t::null)
+            // TODO: Allow null values in additions.
+            SAL_WARN("cui.dialogs", "Additions JSON parse error: " << e.what());
+        }
+    }
+}
+}
+
+AdditionsDialog::AdditionsDialog(weld::Window* pParent)
+    : GenericDialogController(pParent, "cui/ui/additionsdialog.ui", "AdditionsDialog")
+    , m_xEntrySearch(m_xBuilder->weld_entry("entrySearch"))
+    , m_xMenuButtonSettings(m_xBuilder->weld_menu_button("buttonGear"))
+    , m_xContentWindow(m_xBuilder->weld_scrolled_window("contentWindow"))
+    , m_xContentGrid(m_xBuilder->weld_container("contentGrid"))
+{
+    fillGrid();
+}
+
+AdditionsDialog::~AdditionsDialog() {}
+
+void AdditionsDialog::fillGrid()
+{
+    // TODO - Temporary URL
+    OString rURL = "https://yusufketen.com/extensionTest.json";
+    std::string sResponse = curlGet(rURL);
+    std::vector<AdditionInfo> additionInfos;
+    parseResponse(sResponse, additionInfos);
+
+    sal_Int32 i = 0;
+    for (const auto& additionInfo : additionInfos)
+    {
+        m_aAdditionsItems.emplace_back(m_xContentGrid.get());
+        AdditionsItem& aCurrentItem = m_aAdditionsItems.back();
+
+        sal_Int32 nGridPositionY = i++;
+        aCurrentItem.m_xContainer->set_grid_left_attach(0);
+        aCurrentItem.m_xContainer->set_grid_top_attach(nGridPositionY);
+
+        aCurrentItem.m_xLinkButtonName->set_label(additionInfo.sName);
+        aCurrentItem.m_xLinkButtonName->set_uri(additionInfo.sPreviewURL);
+        aCurrentItem.m_xLabelDescription->set_label(additionInfo.sIntroduction);
+        aCurrentItem.m_xLabelAuthor->set_label(additionInfo.sAuthorName);
+        aCurrentItem.m_xButtonInstall->set_label(CuiResId(RID_SVXSTR_ADDITIONS_INSTALLBUTTON));
+        OUString sLicenseString = CuiResId(RID_SVXSTR_ADDITIONS_LICENCE) + additionInfo.sLicense;
+        aCurrentItem.m_xLabelLicense->set_label(sLicenseString);
+        OUString sVersionString
+            = CuiResId(RID_SVXSTR_ADDITIONS_REQUIREDVERSION) + additionInfo.sCompatibleVersion;
+        aCurrentItem.m_xLabelVersion->set_label(sVersionString);
+        aCurrentItem.m_xLinkButtonComments->set_label(additionInfo.sCommentNumber);
+        aCurrentItem.m_xLinkButtonComments->set_uri(additionInfo.sCommentURL);
+        aCurrentItem.m_xLabelDownloadNumber->set_label(additionInfo.sDownloadNumber);
+
+        Reference<XGraphic> xGraphic;
+        try
+        {
+            Reference<XComponentContext> xContext(::comphelper::getProcessComponentContext());
+            Reference<XGraphicProvider> xGraphicProvider(GraphicProvider::create(xContext));
+
+            Sequence<PropertyValue> aMediaProperties(1);
+            aMediaProperties[0].Name = "URL";
+            aMediaProperties[0].Value <<= additionInfo.sScreenshotURL;
+
+            xGraphic = Reference<XGraphic>(xGraphicProvider->queryGraphic(aMediaProperties),
+                                           css::uno::UNO_SET_THROW);
+        }
+        catch (const Exception&)
+        {
+            DBG_UNHANDLED_EXCEPTION("cui.dialogs");
+        }
+
+        aCurrentItem.m_xImageScreenshot->set_image(xGraphic);
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx
index 5784e4e31fc1..d590b570343f 100644
--- a/cui/source/factory/dlgfact.cxx
+++ b/cui/source/factory/dlgfact.cxx
@@ -1421,6 +1421,11 @@ short AbstractAboutDialog_Impl::Execute()
     return m_xDlg->run();
 }
 
+short AbstractAdditionsDialog_Impl::Execute()
+{
+    return m_xDlg->run();
+}
+
 short AbstractTipOfTheDayDialog_Impl::Execute()
 {
     return m_xDlg->run();
@@ -1676,6 +1681,13 @@ VclPtr<AbstractQrCodeGenDialog> AbstractDialogFactory_Impl::CreateQrCodeGenDialo
         std::make_unique<QrCodeGenDialog>(pParent, xModel, bEditExisting));
 }
 
+VclPtr<AbstractAdditionsDialog> AbstractDialogFactory_Impl::CreateAdditionsDialog(
+    weld::Window* pParent)
+{
+    return VclPtr<AbstractAdditionsDialog_Impl>::Create(
+        std::make_unique<AdditionsDialog>(pParent));
+}
+
 VclPtr<AbstractAboutDialog>
 AbstractDialogFactory_Impl::CreateAboutDialog(weld::Window* pParent)
 {
diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx
index 89f9ef88a824..3c0655f30c08 100644
--- a/cui/source/factory/dlgfact.hxx
+++ b/cui/source/factory/dlgfact.hxx
@@ -61,6 +61,7 @@
 #include <tipofthedaydlg.hxx>
 #include <transfrm.hxx>
 #include <zoom.hxx>
+#include <AdditionsDialog.hxx>
 
 class SfxSingleTabDialogController;
 class SfxItemPool;
@@ -753,6 +754,19 @@ public:
     virtual short Execute() override;
 };
 
+class AbstractAdditionsDialog_Impl : public AbstractAdditionsDialog
+{
+protected:
+    std::unique_ptr<AdditionsDialog> m_xDlg;
+
+public:
+    explicit AbstractAdditionsDialog_Impl(std::unique_ptr<AdditionsDialog> p)
+        : m_xDlg(std::move(p))
+    {
+    }
+    virtual short Execute() override;
+};
+
 class TipOfTheDayDialog;
 class AbstractTipOfTheDayDialog_Impl : public AbstractTipOfTheDayDialog
 {
@@ -967,6 +981,9 @@ public:
     CreateQrCodeGenDialog(weld::Window* pParent,
                               const css::uno::Reference<css::frame::XModel> xModel, bool bEditExisting) override;
 
+    virtual VclPtr<AbstractAdditionsDialog>
+    CreateAdditionsDialog(weld::Window* pParent) override;
+
     virtual VclPtr<AbstractAboutDialog> CreateAboutDialog(weld::Window* pParent) override;
 
     virtual VclPtr<AbstractTipOfTheDayDialog> CreateTipOfTheDayDialog(weld::Window* pParent) override;
diff --git a/cui/source/inc/AdditionsDialog.hxx b/cui/source/inc/AdditionsDialog.hxx
new file mode 100644
index 000000000000..ee252e0ea79e
--- /dev/null
+++ b/cui/source/inc/AdditionsDialog.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+
+struct AdditionsItem
+{
+    AdditionsItem(weld::Widget* pParent)
+        : m_xBuilder(Application::CreateBuilder(pParent, "cui/ui/additionsfragment.ui"))
+        , m_xContainer(m_xBuilder->weld_widget("additionsEntry"))
+        , m_xImageScreenshot(m_xBuilder->weld_image("imageScreenshot"))
+        , m_xButtonInstall(m_xBuilder->weld_button("buttonInstall"))
+        , m_xLinkButtonName(m_xBuilder->weld_link_button("linkButtonName"))
+        , m_xLabelAuthor(m_xBuilder->weld_label("labelAuthor"))
+        , m_xLabelDesc(m_xBuilder->weld_label("labelDesc")) // no change (print description)
+        , m_xLabelDescription(m_xBuilder->weld_label("labelDescription"))
+        , m_xLabelLicense(m_xBuilder->weld_label("labelLicense"))
+        , m_xLabelVersion(m_xBuilder->weld_label("labelVersion"))
+        , m_xLabelComments(m_xBuilder->weld_label("labelComments")) // no change
+        , m_xLinkButtonComments(m_xBuilder->weld_link_button("linkButtonComments"))
+        , m_xImageVoting(m_xBuilder->weld_image("imageVoting"))
+        , m_xImageDownloadNumber(m_xBuilder->weld_image("imageDownloadNumber"))
+        , m_xLabelDownloadNumber(m_xBuilder->weld_label("labelDownloadNumber"))
+    {
+    }
+
+    std::unique_ptr<weld::Builder> m_xBuilder;
+    std::unique_ptr<weld::Widget> m_xContainer;
+    std::unique_ptr<weld::Image> m_xImageScreenshot;
+    std::unique_ptr<weld::Button> m_xButtonInstall;
+    std::unique_ptr<weld::LinkButton> m_xLinkButtonName;
+    std::unique_ptr<weld::Label> m_xLabelAuthor;
+    std::unique_ptr<weld::Label> m_xLabelDesc;
+    std::unique_ptr<weld::Label> m_xLabelDescription;
+    std::unique_ptr<weld::Label> m_xLabelLicense;
+    std::unique_ptr<weld::Label> m_xLabelVersion;
+    std::unique_ptr<weld::Label> m_xLabelComments;
+    std::unique_ptr<weld::LinkButton> m_xLinkButtonComments;
+    std::unique_ptr<weld::Image> m_xImageVoting;
+    std::unique_ptr<weld::Image> m_xImageDownloadNumber;
+    std::unique_ptr<weld::Label> m_xLabelDownloadNumber;
+};
+
+class AdditionsDialog : public weld::GenericDialogController
+{
+private:
+    std::unique_ptr<weld::Entry> m_xEntrySearch;
+    std::unique_ptr<weld::MenuButton> m_xMenuButtonSettings;
+    std::vector<AdditionsItem> m_aAdditionsItems;
+
+    std::unique_ptr<weld::ScrolledWindow> m_xContentWindow;
+    std::unique_ptr<weld::Container> m_xContentGrid;
+
+    void fillGrid();
+
+public:
+    AdditionsDialog(weld::Window* pParent);
+    ~AdditionsDialog() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/uiconfig/ui/additionsdialog.ui b/cui/uiconfig/ui/additionsdialog.ui
new file mode 100644
index 000000000000..1eb7736220a1
--- /dev/null
+++ b/cui/uiconfig/ui/additionsdialog.ui
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkDialog" id="AdditionsDialog">
+    <property name="width_request">400</property>
+    <property name="height_request">500</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">6</property>
+    <property name="title" translatable="yes" context="additionsdialog|AdditionsDialog">Additions</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="default_width">500</property>
+    <property name="default_height">1</property>
+    <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="buttonClose">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkSearchEntry" id="entrySearch">
+                    <property name="width_request">275</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="margin_bottom">5</property>
+                    <property name="max_length">150</property>
+                    <property name="primary_icon_name">edit-find-symbolic</property>
+                    <property name="primary_icon_activatable">False</property>
+                    <property name="primary_icon_sensitive">False</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="entrySearch-atkobject">
+                        <property name="AtkObject::accessible-name" translatable="yes" context="additionsdialog|entrySearch">searchEntry</property>
+                        <property name="AtkObject::accessible-description" translatable="yes" context="additionsdialog|entrySearch">searchEntry</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="buttonGear">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="halign">end</property>
+                    <property name="margin_left">1</property>
+                    <property name="use_popover">False</property>
+                    <child>
+                      <object class="GtkImage" id="imageGear">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">sfx2/res/actionaction013.png</property>
+                      </object>
+                    </child>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="buttonGear-atkobject">
+                        <property name="AtkObject::accessible-name" translatable="yes"  context="additionsdialog|buttonGear">Gear Menu</property>
+                        <property name="AtkObject::accessible-description" translatable="yes" context="additionsdialog|buttonGear">Contains commands to modify settings of the additions list such as sorting type or view type.</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="contentWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkGrid" id="contentGrid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="valign">start</property>
+                        <property name="row_spacing">6</property>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-7">buttonClose</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/cui/uiconfig/ui/additionsfragment.ui b/cui/uiconfig/ui/additionsfragment.ui
new file mode 100644
index 000000000000..7ebf69f2a9fa
--- /dev/null
+++ b/cui/uiconfig/ui/additionsfragment.ui
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkGrid" id="additionsEntry">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="valign">start</property>
+    <child>
+      <object class="GtkBox">
+        <property name="width_request">310</property>
+        <property name="height_request">200</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="valign">start</property>
+        <property name="margin_left">5</property>
+        <property name="hexpand">False</property>
+        <property name="vexpand">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkImage" id="imageScreenshot">
+            <property name="width_request">60</property>
+            <property name="height_request">60</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin_top">3</property>
+            <property name="hexpand">False</property>
+            <property name="vexpand">False</property>
+            <property name="stock">gtk-missing-image</property>
+            <accessibility>
+              <relation type="labelled-by" target="labelDescription"/>
+            </accessibility>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="buttonInstall">
+            <property name="label" translatable="yes" context="additionsEntry|buttonInstall">button</property>
+            <property name="width_request">310</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="margin_top">5</property>
+            <property name="hexpand">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">0</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="halign">start</property>
+        <property name="margin_left">5</property>
+        <property name="orientation">vertical</property>
+        <property name="baseline_position">top</property>
+        <child>
+          <object class="GtkLinkButton" id="linkButtonName">
+            <property name="label" translatable="yes" context="additionsEntry|linkButtonName">button</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="halign">start</property>
+            <property name="relief">none</property>
+            <property name="uri">http://glade.gnome.org</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="labelAuthor">
+            <property name="height_request">20</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="label" translatable="yes" context="additionsEntry|labelAuthor">label</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="labelDesc">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="margin_top">3</property>
+            <property name="label" translatable="yes" context="additionsEntry|labelDesc">Description:</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="labelDescription">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="label" translatable="yes" context="additionsEntry|labelDescription">label</property>
+            <property name="wrap">True</property>
+            <property name="wrap_mode">word-char</property>
+            <property name="width_chars">1</property>
+            <property name="max_width_chars">50</property>
+            <accessibility>
+              <relation type="label-for" target="imageScreenshot"/>
+              <relation type="label-for" target="imageVoting"/>
+            </accessibility>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="labelLicense">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="margin_top">3</property>
+            <property name="label" translatable="yes" context="additionsEntry|labelLicense">label</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="labelVersion">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="margin_top">3</property>
+            <property name="label" translatable="yes" context="additionsEntry|labelVersion">label</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">5</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <child>
+              <object class="GtkLabel" id="labelComments">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes" context="additionsEntry|labelComments">Comments:</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLinkButton" id="linkButtonComments">
+                <property name="label" translatable="yes" context="additionsEntry|linkButtonComments">button</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="relief">none</property>
+                <property name="uri">http://glade.gnome.org</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">6</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkImage" id="imageVoting">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="stock">gtk-about</property>
+            <accessibility>
+              <relation type="labelled-by" target="labelDescription"/>
+            </accessibility>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">7</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="margin_top">3</property>
+            <child>
+              <object class="GtkImage" id="imageDownloadNumber">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="stock">gtk-directory</property>
+                <accessibility>
+                  <relation type="labelled-by" target="labelDownloadNumber"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="labelDownloadNumber">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="margin_left">5</property>
+                <property name="label" translatable="yes" context="additionsEntry|labelDownloader">label</property>
+                <accessibility>
+                  <relation type="label-for" target="imageDownloadNumber"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">8</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="top_attach">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index ff2854861930..a42f43c2a702 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -270,6 +270,7 @@ class SvxSearchItem;
 #define SID_LOCK_SAVE                       (SID_SFX_START + 1737)
 #define SID_LOCK_EDITDOC                    (SID_SFX_START + 1738)
 #define SID_REPLACEABLE                     (SID_SFX_START + 1739)
+#define SID_ADDITIONS_DIALOG                (SID_SFX_START + 1740)
 
 //      SID_SFX_free_END                    (SID_SFX_START + 3999)
 
diff --git a/include/vcl/abstdlg.hxx b/include/vcl/abstdlg.hxx
index 1c8d4f968b53..862aa973f2bc 100644
--- a/include/vcl/abstdlg.hxx
+++ b/include/vcl/abstdlg.hxx
@@ -131,6 +131,12 @@ protected:
     virtual ~AbstractAboutDialog() override = default;
 };
 
+class VCL_DLLPUBLIC AbstractAdditionsDialog : public VclAbstractDialog
+{
+protected:
+    virtual ~AbstractAdditionsDialog() override = default;
+};
+
 class VCL_DLLPUBLIC AbstractTipOfTheDayDialog : public VclAbstractDialog
 {
 protected:
@@ -183,6 +189,10 @@ public:
     virtual VclPtr<AbstractAboutDialog>
     CreateAboutDialog(weld::Window* pParent) = 0;
 
+    // create additions dialog
+    virtual VclPtr<AbstractAdditionsDialog>
+        CreateAdditionsDialog(weld::Window* pParent) = 0;
+
     // create info dialog to show tip-of-the-day
     virtual VclPtr<AbstractTipOfTheDayDialog>
     CreateTipOfTheDayDialog(weld::Window* pParent) = 0;
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
index 8735fb5eb8a2..3212c283a6b3 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
@@ -7129,6 +7129,23 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:AdditionsDialog" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">~Additions...</value>
+        </prop>
+        <prop oor:name="ContextLabel" oor:type="xs:string">
+          <value xml:lang="en-US">~Additional Extensions...</value>
+        </prop>
+        <prop oor:name="TooltipLabel" oor:type="xs:string">
+          <value xml:lang="en-US">Additional Extensions</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+        <prop oor:name="IsExperimental" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
+      </node>
       <node oor:name=".uno:FormMoreFieldsMenu" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">More Fields</value>
diff --git a/sc/sdi/tabvwsh.sdi b/sc/sdi/tabvwsh.sdi
index 965e8656d34d..11a8cb46c908 100644
--- a/sc/sdi/tabvwsh.sdi
+++ b/sc/sdi/tabvwsh.sdi
@@ -62,6 +62,7 @@ interface BaseSelection
 
     SID_INSERT_QRCODE           [ ExecMethod = ExecDrawIns; StateMethod = GetDrawInsState; ]
     SID_EDIT_QRCODE             [ ExecMethod = ExecDrawIns; StateMethod = GetDrawInsState; ]
+    SID_ADDITIONS_DIALOG        [ ExecMethod = ExecDrawIns; StateMethod = GetDrawInsState; ]
 
     SID_IMAP                    [ ExecMethod = ExecImageMap; StateMethod = GetImageMapState; ]
     SID_IMAP_EXEC               [ ExecMethod = ExecImageMap; StateMethod = GetImageMapState; ]
diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx
index 9d1c2243c7d1..01f91d325a2a 100644
--- a/sc/source/ui/view/tabvwshb.cxx
+++ b/sc/source/ui/view/tabvwshb.cxx
@@ -413,6 +413,15 @@ void ScTabViewShell::ExecDrawIns(SfxRequest& rReq)
                 break;
             }
 
+        case SID_ADDITIONS_DIALOG:
+            {
+            VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+            ScopedVclPtr<AbstractAdditionsDialog> pDialog(
+                pFact->CreateAdditionsDialog(pWin->GetFrameWeld()));
+            pDialog->Execute();
+            break;
+            }
+
         case SID_OBJECTRESIZE:
             {
                 //         the server would like to change the client size
diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi
index 5053ae628801..6d5d5740a8ed 100644
--- a/sd/sdi/_drvwsh.sdi
+++ b/sd/sdi/_drvwsh.sdi
@@ -2867,6 +2867,11 @@ interface DrawView
         ExecMethod = FuTemporary ;
         StateMethod = GetMenuState ;
     ]
+    SID_ADDITIONS_DIALOG
+    [
+        ExecMethod = FuTemporary ;
+        StateMethod = GetMenuState ;
+    ]
     SID_ATTR_GLOW_COLOR
     [
         ExecMethod = FuTemporary ;
diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx
index 79962d9dbc28..16a31a5f9ebe 100644
--- a/sd/source/ui/view/drviews2.cxx
+++ b/sd/source/ui/view/drviews2.cxx
@@ -3488,6 +3488,17 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq)
         }
         break;
 
+        case SID_ADDITIONS_DIALOG:
+        {
+            VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+            ScopedVclPtr<AbstractAdditionsDialog> pDlg(
+                pFact->CreateAdditionsDialog(GetFrameWeld()));
+            pDlg->Execute();
+            Cancel();
+            rReq.Ignore ();
+        }
+        break;
+
         case SID_ATTR_GLOW_COLOR:
         case SID_ATTR_GLOW_RADIUS:
         case SID_ATTR_GLOW_TRANSPARENCY:
diff --git a/sfx2/sdi/docslots.sdi b/sfx2/sdi/docslots.sdi
index 082baef0f5d5..444dca508c47 100644
--- a/sfx2/sdi/docslots.sdi
+++ b/sfx2/sdi/docslots.sdi
@@ -258,6 +258,11 @@ shell SfxObjectShell
         ExecMethod = ExecFile_Impl ;
         StateMethod = GetState_Impl ;
     ]
+    SID_ADDITIONS_DIALOG
+    [
+        ExecMethod = ExecFile_Impl ;
+        StateMethod = GetState_Impl ;
+    ]
     SID_SIGNATURE
     [
         ExecMethod = ExecFile_Impl;
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index a7d68e7d0a55..19a60a227460 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -5624,3 +5624,20 @@ SfxVoidItem UnicodeNotationToggle SID_UNICODE_NOTATION_TOGGLE
     ToolBoxConfig = FALSE,
     GroupId = SfxGroupId::Options;
 ]
+
+SfxVoidItem AdditionsDialog SID_ADDITIONS_DIALOG
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = TRUE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Application;
+]
diff --git a/sw/sdi/viewsh.sdi b/sw/sdi/viewsh.sdi
index 561b41ff2040..a2dfb805b0d1 100644
--- a/sw/sdi/viewsh.sdi
+++ b/sw/sdi/viewsh.sdi
@@ -66,6 +66,12 @@ interface TextEditView : BaseTextEditView
         StateMethod = GetState ;
         DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
     ]
+    SID_ADDITIONS_DIALOG // status()
+    [
+        ExecMethod = ExecDlgExt ;
+        StateMethod = GetState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
     FN_EDIT_FOOTNOTE // status(final|play)
     [
         ExecMethod = ExecDlgExt ;
diff --git a/sw/source/uibase/uiview/viewdlg2.cxx b/sw/source/uibase/uiview/viewdlg2.cxx
index 0283752c9551..b993aa555046 100644
--- a/sw/source/uibase/uiview/viewdlg2.cxx
+++ b/sw/source/uibase/uiview/viewdlg2.cxx
@@ -74,6 +74,14 @@ void SwView::ExecDlgExt(SfxRequest const &rReq)
             pDialog->Execute();
             break;
         }
+        case SID_ADDITIONS_DIALOG:
+        {
+            VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
+            ScopedVclPtr<AbstractAdditionsDialog> pDialog(
+                pFact->CreateAdditionsDialog(GetFrameWeld()));
+            pDialog->Execute();
+            break;
+        }
         case SID_SIGN_SIGNATURELINE:
         {
             VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();


More information about the Libreoffice-commits mailing list