tdf#44462: add a link to Windows Default apps settings applet

Add "Windows Default apps" button to Options->General to run system applet
to control file associations, in accordance to recommendation from MS [1].
On Windows 10, though, the call to LaunchAdvancedAssociationUI would only
bring a system-modal infobanner suggesting the user to go to Settings >
Apps > Default apps, as documented at [2]. Since this is what MS considers
the correct way to manage application associations, the infobanner should
be enough.

[1] https://docs.microsoft.com/en-us/windows/win32/shell/default-programs
[2] https://docs.microsoft.com/en-us/windows/win32/api/shobjidl/nf-shobjidl-iapplicationassociationregistrationui-launchadvancedassociationui

Change-Id: I79cccdd00afac998c028b8e151db66bbd75be985
Reviewed-on: https://gerrit.libreoffice.org/82777
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk
index e45e35a..27d89ec 100644
--- a/cui/Library_cui.mk
+++ b/cui/Library_cui.mk
@@ -87,6 +87,7 @@ ifeq ($(OS),WNT)
$(eval $(call gb_Library_use_system_win32_libs,cui,\
    advapi32 \
    shlwapi \
    ole32 \
))
endif

diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx
index 3079b2c..597d753 100644
--- a/cui/source/options/optgdlg.cxx
+++ b/cui/source/options/optgdlg.cxx
@@ -81,6 +81,12 @@
#include <svtools/restartdialog.hxx>
#include <svtools/imgdef.hxx>

#if defined(_WIN32)
#include <o3tl/char16_t2wchar_t.hxx>
#include <prewin.h>
#include <shobjidl.h>
#include <postwin.h>
#endif
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
@@ -248,6 +254,10 @@ OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* p
#else
    , m_xQuickLaunchCB(m_xBuilder->weld_check_button("quicklaunch"))
#endif
#if defined(_WIN32)
    , m_xFileAssocFrame(m_xBuilder->weld_widget("fileassoc"))
    , m_xFileAssocBtn(m_xBuilder->weld_button("assocfiles"))
#endif
{
    if (!lcl_HasSystemFilePicker())
        m_xFileDlgFrame->hide();
@@ -273,6 +283,11 @@ OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* p
    m_xQuickStarterFrame->hide();
#endif

#if defined(_WIN32)
    m_xFileAssocFrame->show();
    m_xFileAssocBtn->connect_clicked(LINK(this, OfaMiscTabPage, FileAssocClick));
#endif

    m_aStrDateInfo = m_xToYearFT->get_label();
    m_xYearValueField->connect_value_changed( LINK( this, OfaMiscTabPage, TwoFigureHdl ) );

@@ -427,6 +442,30 @@ IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void )
    m_xToYearFT->set_label( aOutput );
}

#if defined(_WIN32)
IMPL_LINK_NOARG(OfaMiscTabPage, FileAssocClick, weld::Button&, void)
{
    const bool bUninit = SUCCEEDED(CoInitialize(nullptr));
    IApplicationAssociationRegistrationUI* pIf = nullptr;
    HRESULT res = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI, 0,
                                   CLSCTX_INPROC_SERVER, IID_IApplicationAssociationRegistrationUI,
                                   reinterpret_cast<LPVOID*>(&pIf));

    if (SUCCEEDED(res) && pIf)
    {
        // LaunchAdvancedAssociationUI only works for applications registered under
        // Software\RegisteredApplications. See scp2/source/ooo/registryitem_ooo.scp
        const OUString expanded = Translate::ExpandVariables("%PRODUCTNAME %PRODUCTVERSION");
        // This will only show "To change your default apps, go to Settings > Apps > Default apps"
        // on Win10; this is expected. At least this will self-document it to users.
        pIf->LaunchAdvancedAssociationUI(o3tl::toW(expanded.getStr()));
        pIf->Release();
    }
    if (bUninit)
        CoUninitialize();
}
#endif

class CanvasSettings
{
public:
diff --git a/cui/source/options/optgdlg.hxx b/cui/source/options/optgdlg.hxx
index 5c591e7..392554f 100644
--- a/cui/source/options/optgdlg.hxx
+++ b/cui/source/options/optgdlg.hxx
@@ -54,8 +54,15 @@ private:
    std::unique_ptr<weld::CheckButton> m_xCrashReport;
    std::unique_ptr<weld::Widget> m_xQuickStarterFrame;
    std::unique_ptr<weld::CheckButton> m_xQuickLaunchCB;
#if defined(_WIN32)
    std::unique_ptr<weld::Widget> m_xFileAssocFrame;
    std::unique_ptr<weld::Button> m_xFileAssocBtn;
#endif

    DECL_LINK(TwoFigureHdl, weld::SpinButton&, void);
#if defined(_WIN32)
    DECL_LINK(FileAssocClick, weld::Button&, void);
#endif
protected:
    virtual DeactivateRC   DeactivatePage( SfxItemSet* pSet ) override;

diff --git a/cui/uiconfig/ui/optgeneralpage.ui b/cui/uiconfig/ui/optgeneralpage.ui
index dc1fa22..87ff247f 100644
--- a/cui/uiconfig/ui/optgeneralpage.ui
+++ b/cui/uiconfig/ui/optgeneralpage.ui
@@ -450,5 +450,56 @@
        <property name="top_attach">6</property>
      </packing>
    </child>
    <child>
      <object class="GtkFrame" id="fileassoc">
        <property name="can_focus">False</property>
        <property name="label_xalign">0</property>
        <property name="shadow_type">none</property>
        <child>
          <object class="GtkAlignment" id="alignment8">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="top_padding">6</property>
            <property name="left_padding">12</property>
            <child>
              <object class="GtkGrid" id="grid8">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="row_spacing">6</property>
                <child>
                  <object class="GtkButton" id="assocfiles">
                    <property name="visible">True</property>
                    <property name="label" translatable="yes" context="optgeneralpage|fileassoc">Windows Default apps</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="no_show_all">True</property>
                    <property name="use_underline">True</property>
                    <property name="draw_indicator">True</property>
                  </object>
                  <packing>
                    <property name="left_attach">0</property>
                    <property name="top_attach">0</property>
                  </packing>
                </child>
              </object>
            </child>
          </object>
        </child>
        <child type="label">
          <object class="GtkLabel" id="label9">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes" context="optgeneralpage|fileassoc">%PRODUCTNAME File Associations</property>
            <attributes>
              <attribute name="weight" value="bold"/>
            </attributes>
          </object>
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">7</property>
      </packing>
    </child>
  </object>
</interface>