diff options
-rw-r--r-- | cui/Library_cui.mk | 5 | ||||
-rw-r--r-- | cui/UIConfig_cui.mk | 6 | ||||
-rw-r--r-- | cui/source/dialogs/fileextcheckdlg.cxx | 55 | ||||
-rw-r--r-- | cui/source/factory/dlgfact.cxx | 11 | ||||
-rw-r--r-- | cui/source/factory/dlgfact.hxx | 6 | ||||
-rw-r--r-- | cui/source/inc/fileextcheckdlg.hxx | 39 | ||||
-rw-r--r-- | cui/source/options/optgdlg.cxx | 43 | ||||
-rw-r--r-- | cui/source/options/optgdlg.hxx | 1 | ||||
-rw-r--r-- | cui/uiconfig/ui/fileextcheckdialog.ui | 109 | ||||
-rw-r--r-- | cui/uiconfig/ui/optgeneralpage.ui | 15 | ||||
-rw-r--r-- | desktop/source/app/app.cxx | 10 | ||||
-rw-r--r-- | include/vcl/abstdlg.hxx | 6 | ||||
-rw-r--r-- | include/vcl/fileregistration.hxx | 21 | ||||
-rw-r--r-- | officecfg/registry/data/org/openoffice/Office/Common.xcu | 3 | ||||
-rw-r--r-- | officecfg/registry/schema/org/openoffice/Office/Common.xcs | 7 | ||||
-rw-r--r-- | solenv/sanitizers/ui/cui.suppr | 1 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/strings.hrc | 3 | ||||
-rw-r--r-- | vcl/win/app/fileregistration.cxx | 198 |
19 files changed, 514 insertions, 26 deletions
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk index f2df06cc5f2c..d6fa68e0d194 100644 --- a/cui/Library_cui.mk +++ b/cui/Library_cui.mk @@ -85,7 +85,10 @@ ifeq ($(OS),WNT) $(eval $(call gb_Library_use_system_win32_libs,cui,\ advapi32 \ shlwapi \ - ole32 \ +)) + +$(eval $(call gb_Library_add_exception_objects,cui,\ + cui/source/dialogs/fileextcheckdlg \ )) endif diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk index 153d6fe98fda..ff3c718b21d6 100644 --- a/cui/UIConfig_cui.mk +++ b/cui/UIConfig_cui.mk @@ -9,6 +9,12 @@ $(eval $(call gb_UIConfig_UIConfig,cui)) +ifeq ($(OS),WNT) +$(eval $(call gb_UIConfig_add_uifiles,cui,\ + cui/uiconfig/ui/fileextcheckdialog \ +)) +endif + $(eval $(call gb_UIConfig_add_uifiles,cui,\ cui/uiconfig/ui/aboutdialog \ cui/uiconfig/ui/aboutconfigdialog\ diff --git a/cui/source/dialogs/fileextcheckdlg.cxx b/cui/source/dialogs/fileextcheckdlg.cxx new file mode 100644 index 000000000000..732f8367436a --- /dev/null +++ b/cui/source/dialogs/fileextcheckdlg.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <officecfg/Office/Common.hxx> +#include <vcl/fileregistration.hxx> + +#include <fileextcheckdlg.hxx> + +FileExtCheckDialog::FileExtCheckDialog(weld::Window* pParent, const OUString& sTitle, + const OUString& sMsg) + : GenericDialogController(pParent, "cui/ui/fileextcheckdialog.ui", "FileExtCheckDialog") + , m_pText(m_xBuilder->weld_label("lbText")) + , m_pPerformCheck(m_xBuilder->weld_check_button("cbPerformCheck")) + , m_pOk(m_xBuilder->weld_button("btnOk")) +{ + m_pPerformCheck->set_active(true); + m_pOk->connect_clicked(LINK(this, FileExtCheckDialog, OnOkClick)); + m_xDialog->set_title(sTitle); + m_pText->set_label(sMsg); +} + +FileExtCheckDialog::~FileExtCheckDialog() +{ + std::shared_ptr<comphelper::ConfigurationChanges> xChanges( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Misc::PerformFileExtCheck::set(m_pPerformCheck->get_active(), + xChanges); + xChanges->commit(); +} + +IMPL_LINK_NOARG(FileExtCheckDialog, OnOkClick, weld::Button&, void) +{ + vcl::fileregistration::LaunchRegistrationUI(); + FileExtCheckDialog::response(RET_OK); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx index d371224ffa20..25f2c6f124af 100644 --- a/cui/source/factory/dlgfact.cxx +++ b/cui/source/factory/dlgfact.cxx @@ -90,6 +90,7 @@ #include <tipofthedaydlg.hxx> #include <toolbarmodedlg.hxx> #include <DiagramDialog.hxx> +#include <fileextcheckdlg.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::frame; @@ -1699,4 +1700,14 @@ AbstractDialogFactory_Impl::CreateDiagramDialog(weld::Window* pParent, std::shar std::make_unique<DiagramDialog>(pParent, pDiagramData)); } +#ifdef _WIN32 +VclPtr<VclAbstractDialog> +AbstractDialogFactory_Impl::CreateFileExtCheckDialog(weld::Window* pParent, const OUString& sTitle, + const OUString& sMsg) +{ + return VclPtr<CuiAbstractController_Impl>::Create( + std::make_unique<FileExtCheckDialog>(pParent, sTitle, sMsg)); +} +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx index 7d97167193b8..2d7afbe6f6a1 100644 --- a/cui/source/factory/dlgfact.hxx +++ b/cui/source/factory/dlgfact.hxx @@ -945,6 +945,12 @@ public: virtual VclPtr<AbstractDiagramDialog> CreateDiagramDialog( weld::Window* pParent, std::shared_ptr<DiagramDataInterface> pDiagramData) override; + +#ifdef _WIN32 + virtual VclPtr<VclAbstractDialog> CreateFileExtCheckDialog(weld::Window* pParent, + const OUString& sTitle, + const OUString& sMsg) override; +#endif }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/fileextcheckdlg.hxx b/cui/source/inc/fileextcheckdlg.hxx new file mode 100644 index 000000000000..968deae77177 --- /dev/null +++ b/cui/source/inc/fileextcheckdlg.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <sal/config.h> + +#include <vcl/weld.hxx> + +class FileExtCheckDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr<weld::Label> m_pText; + std::unique_ptr<weld::CheckButton> m_pPerformCheck; + std::unique_ptr<weld::Button> m_pOk; + + DECL_LINK(OnOkClick, weld::Button&, void); + +public: + FileExtCheckDialog(weld::Window* pWindow, const OUString& sTitle, const OUString& sMsg); + virtual ~FileExtCheckDialog() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx index 673815bb60ab..7ec04487d5c0 100644 --- a/cui/source/options/optgdlg.cxx +++ b/cui/source/options/optgdlg.cxx @@ -86,11 +86,7 @@ #include <svtools/imgdef.hxx> #if defined(_WIN32) -#include <o3tl/char16_t2wchar_t.hxx> -#include <prewin.h> -#include <shobjidl.h> -#include <systools/win32/comtools.hxx> -#include <postwin.h> +#include <vcl/fileregistration.hxx> #endif using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; @@ -177,6 +173,7 @@ OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* p #endif #if defined(_WIN32) , m_xFileAssocFrame(m_xBuilder->weld_widget("fileassoc")) + , m_xPerformFileExtCheck(m_xBuilder->weld_check_button("cbPerformFileExtCheck")) , m_xFileAssocBtn(m_xBuilder->weld_button("assocfiles")) #endif { @@ -288,6 +285,15 @@ bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet ) } #endif +#if defined(_WIN32) + if (m_xPerformFileExtCheck->get_state_changed_from_saved()) + { + officecfg::Office::Common::Misc::PerformFileExtCheck::set( + m_xPerformFileExtCheck->get_active(), batch); + bModified = true; + } +#endif + batch->commit(); if( m_xQuickLaunchCB->get_state_changed_from_saved()) @@ -347,6 +353,12 @@ void OfaMiscTabPage::Reset( const SfxItemSet* rSet ) } m_xQuickLaunchCB->save_state(); + +#if defined(_WIN32) + m_xPerformFileExtCheck->set_active( + officecfg::Office::Common::Misc::PerformFileExtCheck::get()); + m_xPerformFileExtCheck->save_state(); +#endif } IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void ) @@ -367,26 +379,7 @@ IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void ) #if defined(_WIN32) IMPL_STATIC_LINK_NOARG(OfaMiscTabPage, FileAssocClick, weld::Button&, void) { - const bool bUninit = SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); - try - { - auto pIf - = sal::systools::COMReference<IApplicationAssociationRegistrationUI>().CoCreateInstance( - CLSID_ApplicationAssociationRegistrationUI, nullptr, CLSCTX_INPROC_SERVER); - - // 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())); - } - catch (...) - { - // Just ignore any error here: this is not something we need to make sure to succeed - } - if (bUninit) - CoUninitialize(); + vcl::fileregistration::LaunchRegistrationUI(); } #endif diff --git a/cui/source/options/optgdlg.hxx b/cui/source/options/optgdlg.hxx index 07d3cca86fb7..d9a55ced7fb1 100644 --- a/cui/source/options/optgdlg.hxx +++ b/cui/source/options/optgdlg.hxx @@ -52,6 +52,7 @@ private: #if defined(_WIN32) std::unique_ptr<weld::Widget> m_xFileAssocFrame; std::unique_ptr<weld::Button> m_xFileAssocBtn; + std::unique_ptr<weld::CheckButton> m_xPerformFileExtCheck; #endif DECL_LINK(TwoFigureHdl, weld::SpinButton&, void); diff --git a/cui/uiconfig/ui/fileextcheckdialog.ui b/cui/uiconfig/ui/fileextcheckdialog.ui new file mode 100644 index 000000000000..c5661134ca20 --- /dev/null +++ b/cui/uiconfig/ui/fileextcheckdialog.ui @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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/. + * +--> +<interface domain="cui"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkDialog" id="FileExtCheckDialog"> + <property name="can-focus">False</property> + <property name="border-width">6</property> + <property name="title" translatable="yes" context="FileExtCheckDialog|Name"></property> + <property name="resizable">False</property> + <property name="modal">True</property> + <property name="window-position">center-on-parent</property> + <property name="type-hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="layout-style">end</property> + <child> + <object class="GtkCheckButton" id="cbPerformCheck"> + <property name="label" translatable="yes" context="FileExtCheck|Checkbox">_Perform check on startup</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes" context="FileExtCheck|Checkbox_Tooltip">Enable the dialog again at Tools > Options > General</property> + <property name="use-underline">True</property> + <property name="active">True</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + <property name="secondary">True</property> + </packing> + </child> + <child> + <object class="GtkButton" id="btnCancel"> + <property name="label" translatable="yes" context="stock">_Cancel</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="btnOk"> + <property name="label" translatable="yes" context="FileExtCheckDialog|Ok_Button">_OK</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="has-focus">True</property> + <property name="is-focus">True</property> + <property name="can-default">True</property> + <property name="has-default">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="lbText"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="vexpand">True</property> + <property name="wrap">True</property> + <property name="width-chars">50</property> + <property name="max-width-chars">50</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-5">btnCancel</action-widget> + </action-widgets> + </object> +</interface> diff --git a/cui/uiconfig/ui/optgeneralpage.ui b/cui/uiconfig/ui/optgeneralpage.ui index 3380a2f228af..5f502977f26e 100644 --- a/cui/uiconfig/ui/optgeneralpage.ui +++ b/cui/uiconfig/ui/optgeneralpage.ui @@ -15,6 +15,7 @@ <property name="can_focus">False</property> <property name="border_width">6</property> <property name="row_spacing">12</property> + <property name="vexpand">True</property> <child> <object class="GtkFrame" id="frame1"> <property name="visible">True</property> @@ -453,6 +454,20 @@ <property name="top_attach">0</property> </packing> </child> + <child> + <object class="GtkCheckButton" id="cbPerformFileExtCheck"> + <property name="label" translatable="yes" context="optgeneralpage|FileExtCheckCheckbox">Perform check for default file associations on start-up</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> </object> </child> <child type="label"> diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index 90a98d0506b0..8b4d7b34f4d4 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -131,6 +131,7 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <vcl/fileregistration.hxx> #endif #if defined(_WIN32) @@ -1893,6 +1894,15 @@ IMPL_LINK_NOARG(Desktop, OpenClients_Impl, void*, void) CloseSplashScreen(); CheckFirstRun( ); #ifdef _WIN32 + bool bDontShowDialogs + = Application::IsHeadlessModeEnabled(); // uitest.uicheck fails when the dialog is open + for (sal_uInt16 i = 0; !bDontShowDialogs && i < Application::GetCommandLineParamCount(); i++) + { + if (Application::GetCommandLineParam(i) == "--nologo") + bDontShowDialogs = true; + } + if (!bDontShowDialogs) + vcl::fileregistration::CheckFileExtRegistration(SfxGetpApp()->GetTopWindow()); // Registers a COM class factory of the service manager with the windows operating system. Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory(); xSMgr->createInstance("com.sun.star.bridge.OleApplicationRegistration"); diff --git a/include/vcl/abstdlg.hxx b/include/vcl/abstdlg.hxx index 2a58f6af7355..52212f482253 100644 --- a/include/vcl/abstdlg.hxx +++ b/include/vcl/abstdlg.hxx @@ -180,6 +180,12 @@ public: virtual VclPtr<AbstractDiagramDialog> CreateDiagramDialog( weld::Window* pParent, std::shared_ptr<DiagramDataInterface> pDiagramData) = 0; + +#ifdef _WIN32 + virtual VclPtr<VclAbstractDialog> + CreateFileExtCheckDialog(weld::Window* _pParent, const OUString& sTitle, const OUString& sMsg) + = 0; +#endif }; #endif diff --git a/include/vcl/fileregistration.hxx b/include/vcl/fileregistration.hxx new file mode 100644 index 000000000000..3dd16f728cc9 --- /dev/null +++ b/include/vcl/fileregistration.hxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <sal/config.h> + +namespace vcl::fileregistration +{ +VCL_DLLPUBLIC void LaunchRegistrationUI(); + +VCL_DLLPUBLIC void CheckFileExtRegistration(weld::Window* pDialogParent); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/officecfg/registry/data/org/openoffice/Office/Common.xcu b/officecfg/registry/data/org/openoffice/Office/Common.xcu index 237348be96cb..2144d43a5454 100644 --- a/officecfg/registry/data/org/openoffice/Office/Common.xcu +++ b/officecfg/registry/data/org/openoffice/Office/Common.xcu @@ -467,6 +467,9 @@ <prop oor:name="FindReplaceRememberedSearches"> <value>10</value> </prop> + <prop oor:name="PerformFileExtCheck"> + <value install:module="wnt">true</value> + </prop> </node> <node oor:name="Save"> <node oor:name="ODF"> diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index 5f51032addb5..91bf8142c72f 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -5665,6 +5665,13 @@ </info> <value>-1</value> </prop> + <prop oor:name="PerformFileExtCheck" oor:type="xs:boolean" oor:nillable="false"> + <!-- UIHints: Tools - Options - General --> + <info> + <desc>Determines whether the default file extension check is performed on startup.</desc> + </info> + <value>false</value> + </prop> <prop oor:name="UseOpenCL" oor:type="xs:boolean" oor:nillable="false"> <info> <desc>Determines whether OpenCL can be used, when available, to speed up diff --git a/solenv/sanitizers/ui/cui.suppr b/solenv/sanitizers/ui/cui.suppr index f250aa945ab8..f7c838a8a349 100644 --- a/solenv/sanitizers/ui/cui.suppr +++ b/solenv/sanitizers/ui/cui.suppr @@ -117,6 +117,7 @@ cui/uiconfig/ui/iconchangedialog.ui://GtkLabel[@id='label1'] orphan-label cui/uiconfig/ui/iconselectordialog.ui://GtkLabel[@id='noteLabel'] orphan-label cui/uiconfig/ui/tipofthedaydialog.ui://GtkLabel[@id='lbTitle'] orphan-label cui/uiconfig/ui/tipofthedaydialog.ui://GtkLabel[@id='lbText'] orphan-label +cui/uiconfig/ui/fileextcheckdialog.ui://GtkLabel[@id='lbText'] orphan-label cui/uiconfig/ui/insertfloatingframe.ui://GtkLabel[@id='label6'] orphan-label cui/uiconfig/ui/insertfloatingframe.ui://GtkLabel[@id='label7'] orphan-label cui/uiconfig/ui/insertfloatingframe.ui://GtkLabel[@id='widthlabel'] orphan-label diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 4ffb346ca2e1..fba19b4e5fb3 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -749,6 +749,7 @@ ifeq ($(OS),WNT) $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/opengl/win/WinDeviceInfo \ vcl/source/app/salplug \ + vcl/win/app/fileregistration \ )) $(eval $(call gb_Library_use_system_win32_libs,vcl,\ diff --git a/vcl/inc/strings.hrc b/vcl/inc/strings.hrc index 11b9268f2e1f..2acb7bf45e0c 100644 --- a/vcl/inc/strings.hrc +++ b/vcl/inc/strings.hrc @@ -135,6 +135,9 @@ #define STR_SEPARATOR NC_("STR_SEPARATOR", "Separator") +#define STR_FILEEXT_NONDEFAULT_ASK_TITLE NC_("STR_FILEEXT_NONDEFAULT_ASK_TITLE", "Default file formats not registered") +#define STR_FILEEXT_NONDEFAULT_ASK_MSG NC_("STR_FILEEXT_NONDEFAULT_ASK_MSG", "The following file formats are not registered to be opened by default in %PRODUCTNAME:\n$1\nSelect OK if you want to change default file format registrations.") + #define KEY_VERSION_CHECK NC_("KEY_VERSION_CHECK", "Warning: Not all of the imported EPS graphics could be saved at level1\nas some are at a higher level!") #endif // INCLUDED_VCL_INC_STRINGS_HRC diff --git a/vcl/win/app/fileregistration.cxx b/vcl/win/app/fileregistration.cxx new file mode 100644 index 000000000000..863e66d0a3b1 --- /dev/null +++ b/vcl/win/app/fileregistration.cxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#if !defined(NTDDI_VERSION) || NTDDI_VERSION < NTDDI_WIN8 +#define NTDDI_VERSION NTDDI_WIN8 // needed for IApplicationActivationManager +#endif + +#include <sal/config.h> + +#include <comphelper/scopeguard.hxx> +#include <o3tl/char16_t2wchar_t.hxx> +#include <vcl/abstdlg.hxx> +#include <vcl/fileregistration.hxx> + +#include <strings.hrc> + +#include <prewin.h> +#include <Shobjidl.h> +#include <systools/win32/comtools.hxx> +#include <versionhelpers.h> +#include <postwin.h> + +#define MAX_LONG_PATH 32767 + +namespace vcl::fileregistration +{ +static void LaunchModernSettingsDialogDefaultApps() +{ + auto pIf = sal::systools::COMReference<IApplicationActivationManager>().CoCreateInstance( + CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER); + + DWORD pid; + HRESULT hr = pIf->ActivateApplication(L"windows.immersivecontrolpanel_cw5n1h2txyewy" + L"!microsoft.windows.immersivecontrolpanel", + L"page=SettingsPageAppsDefaults", AO_NONE, &pid); + if (SUCCEEDED(hr)) + { + // Do not check error because we could at least open + // the "Default apps" setting. + pIf->ActivateApplication(L"windows.immersivecontrolpanel_cw5n1h2txyewy" + L"!microsoft.windows.immersivecontrolpanel", + L"page=SettingsPageAppsDefaults" + L"&target=SettingsPageAppsDefaultsDefaultAppsListView", + AO_NONE, &pid); + } +} + +static HRESULT +IsPathDefaultForClass(sal::systools::COMReference<IApplicationAssociationRegistration>& pAAR, + LPCWSTR aClassName, LPCWSTR progID) +{ + // Make sure the Prog ID matches what we have + LPWSTR registeredApp; + HRESULT hr + = pAAR->QueryCurrentDefault(aClassName, AT_FILEEXTENSION, AL_EFFECTIVE, ®isteredApp); + if (FAILED(hr)) + { + return hr; + } + + if (!wcsnicmp(registeredApp, progID, wcslen(progID))) + hr = S_OK; + else + hr = S_FALSE; + + CoTaskMemFree(registeredApp); + + return hr; +} + +static bool IsDefaultAppInstalledInReg() +{ + const wchar_t* keyPath = L"SOFTWARE\\LibreOffice\\UNO\\InstallPath"; + + WCHAR szRegPath[MAX_LONG_PATH]; + DWORD cbData = static_cast<DWORD>(MAX_LONG_PATH * sizeof(WCHAR)); + auto rc = RegGetValueW(HKEY_LOCAL_MACHINE, keyPath, nullptr, RRF_RT_REG_SZ, nullptr, + static_cast<PVOID>(szRegPath), &cbData); + if (rc != ERROR_SUCCESS) + return false; + + WCHAR szProcPath[MAX_LONG_PATH]; + if (!GetModuleFileNameW(NULL, szProcPath, MAX_LONG_PATH)) + return false; + + WCHAR szFullProcPath[MAX_LONG_PATH]; + if (!GetFullPathNameW(szProcPath, MAX_LONG_PATH, szFullProcPath, NULL)) + return false; + + if (!GetLongPathNameW(szFullProcPath, szFullProcPath, MAX_LONG_PATH)) + return false; + + if (!GetLongPathNameW(szRegPath, szRegPath, MAX_LONG_PATH)) + return false; + + if (wcslen(szRegPath) > 0 && wcsstr(szFullProcPath, szRegPath) != NULL) + return true; + + return false; +} + +void LaunchRegistrationUI() +{ + const bool bUninit = SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + comphelper::ScopeGuard g([bUninit]() { + if (bUninit) + CoUninitialize(); + }); + + try + { + if (IsWindows10OrGreater()) + { + LaunchModernSettingsDialogDefaultApps(); + } + else + { + auto pIf = sal::systools::COMReference<IApplicationAssociationRegistrationUI>() + .CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI, nullptr, + CLSCTX_INPROC_SERVER); + + // LaunchAdvancedAssociationUI only works for applications registered under + // Software\RegisteredApplications. See scp2/source/ooo/registryitem_ooo.scp + const OUString expanded = Translate::ExpandVariables("%PRODUCTNAME %PRODUCTVERSION"); + pIf->LaunchAdvancedAssociationUI(o3tl::toW(expanded.getStr())); + } + } + catch (...) + { + // Just ignore any error here: this is not something we need to make sure to succeed + } +} + +void CheckFileExtRegistration(weld::Window* pDialogParent) +{ + if (!officecfg::Office::Common::Misc::PerformFileExtCheck::get()) + return; + + if (!IsDefaultAppInstalledInReg()) + return; + + const bool bUninit = SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + comphelper::ScopeGuard g([bUninit]() { + if (bUninit) + CoUninitialize(); + }); + sal::systools::COMReference<IApplicationAssociationRegistration> pAAR = nullptr; + try + { + pAAR = sal::systools::COMReference<IApplicationAssociationRegistration>().CoCreateInstance( + CLSID_ApplicationAssociationRegistration, nullptr, CLSCTX_INPROC_SERVER); + } + catch (...) + { + // Just return on any error here: this is not something we need to make sure to succeed + return; + } + + std::map<OUString, OUString> formats = { + { ".odp", "LibreOffice.ImpressDocument.1" }, + { ".odt", "LibreOffice.WriterDocument.1" }, + { ".ods", "LibreOffice.CalcDocument.1" }, + }; + OUString aNonDefaults; + bool isNotDefault = false; + + for (std::map<OUString, OUString>::iterator it = formats.begin(); it != formats.end(); it++) + { + if (IsPathDefaultForClass(pAAR, o3tl::toW(it->first.getStr()), + o3tl::toW(it->second.getStr())) + == S_FALSE) + { + isNotDefault = true; + aNonDefaults += it->first; + aNonDefaults += "\n"; + } + } + + if (isNotDefault) + { + OUString aMsg(VclResId(STR_FILEEXT_NONDEFAULT_ASK_MSG)); + aMsg = aMsg.replaceFirst("$1", aNonDefaults); + + VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create(); + ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateFileExtCheckDialog( + pDialogParent, VclResId(STR_FILEEXT_NONDEFAULT_ASK_TITLE), aMsg)); + pDlg->Execute(); + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |