1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/processfactory.hxx>
21 #include <rtl/bootstrap.hxx>
22 #include <config_folders.h>
23 #include <CustomNotebookbarGenerator.hxx>
24 #include <osl/file.hxx>
25 #include <osl/thread.h>
26 #include <vcl/EnumContext.hxx>
27 #include <vcl/settings.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <com/sun/star/frame/ModuleManager.hpp>
30 #include <unotools/confignode.hxx>
31 #include <libxml/parser.h>
32 #include <o3tl/string_view.hxx>
34 #define aUIPropertiesCount 3
38 CustomNotebookbarGenerator::CustomNotebookbarGenerator() {}
40 static OUString
lcl_activeAppName(vcl::EnumContext::Application eApp
)
44 case vcl::EnumContext::Application::Writer
:
45 return "ActiveWriter";
46 case vcl::EnumContext::Application::Calc
:
48 case vcl::EnumContext::Application::Impress
:
49 return "ActiveImpress";
50 case vcl::EnumContext::Application::Draw
:
57 static OUString
lcl_getAppName(vcl::EnumContext::Application eApp
)
61 case vcl::EnumContext::Application::Writer
:
63 case vcl::EnumContext::Application::Calc
:
65 case vcl::EnumContext::Application::Impress
:
67 case vcl::EnumContext::Application::Draw
:
74 static OUString
getAppNameRegistryPath()
76 vcl::EnumContext::Application eApp
= vcl::EnumContext::Application::Any
;
78 if (SfxViewFrame
* pViewFrame
= SfxViewFrame::Current())
80 const Reference
<frame::XFrame
>& xFrame
= pViewFrame
->GetFrame().GetFrameInterface();
81 const Reference
<frame::XModuleManager
> xModuleManager
82 = frame::ModuleManager::create(::comphelper::getProcessComponentContext());
83 eApp
= vcl::EnumContext::GetApplicationEnum(xModuleManager
->identify(xFrame
));
86 OUString
sAppName(lcl_getAppName(eApp
));
87 return "org.openoffice.Office.UI.ToolbarMode/Applications/" + sAppName
;
90 static OUString
customizedUIPathBuffer()
92 OUString
sDirPath("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
93 "bootstrap") ":UserInstallation}/user/config/soffice.cfg/");
94 rtl::Bootstrap::expandMacros(sDirPath
);
98 OUString
CustomNotebookbarGenerator::getCustomizedUIPath()
100 OUString sAppName
, sNotebookbarUIFileName
;
101 CustomNotebookbarGenerator::getFileNameAndAppName(sAppName
, sNotebookbarUIFileName
);
102 return customizedUIPathBuffer() + "modules/s" + sAppName
.toAsciiLowerCase() + "/ui/"
103 + sNotebookbarUIFileName
;
106 OUString
CustomNotebookbarGenerator::getOriginalUIPath()
108 OUString sAppName
, sNotebookbarUIFileName
;
109 CustomNotebookbarGenerator::getFileNameAndAppName(sAppName
, sNotebookbarUIFileName
);
110 return AllSettings::GetUIRootDir() + "modules/s" + sAppName
.toAsciiLowerCase() + "/ui/"
111 + sNotebookbarUIFileName
;
114 static OUString
getUIDirPath()
116 OUString sAppName
, sNotebookbarUIFileName
;
117 CustomNotebookbarGenerator::getFileNameAndAppName(sAppName
, sNotebookbarUIFileName
);
119 = customizedUIPathBuffer() + "modules/s" + sAppName
.toAsciiLowerCase() + "/ui/";
123 OString
CustomNotebookbarGenerator::getSystemPath(OUString
const& sURL
)
127 OUString sSystemPathSettings
;
128 if (osl_getSystemPathFromFileURL(sURL
.pData
, &sSystemPathSettings
.pData
) != osl_File_E_None
)
130 SAL_WARN("cui.customnotebookbar", "Cannot get system path for :" << sURL
);
133 OString osSystemPathSettings
134 = OUStringToOString(sSystemPathSettings
, osl_getThreadTextEncoding());
135 return osSystemPathSettings
;
138 static void changeNodeValue(xmlNode
* pNodePtr
, const char* pProperty
, const char* pValue
)
140 pNodePtr
= pNodePtr
->xmlChildrenNode
;
143 if (!(xmlStrcmp(pNodePtr
->name
, reinterpret_cast<const xmlChar
*>("property"))))
145 xmlChar
* UriValue
= xmlGetProp(pNodePtr
, reinterpret_cast<const xmlChar
*>("name"));
146 if (!(xmlStrcmp(UriValue
, reinterpret_cast<const xmlChar
*>(pProperty
))))
147 xmlNodeSetContent(pNodePtr
, reinterpret_cast<const xmlChar
*>(pValue
));
151 pNodePtr
= pNodePtr
->next
;
155 static void searchNodeAndAttribute(xmlNode
* pNodePtr
, const char* pUIItemID
, const char* pProperty
,
158 pNodePtr
= pNodePtr
->xmlChildrenNode
;
161 if (pNodePtr
->type
== XML_ELEMENT_NODE
)
163 if (!(xmlStrcmp(pNodePtr
->name
, reinterpret_cast<const xmlChar
*>("object"))))
165 xmlChar
* UriValue
= xmlGetProp(pNodePtr
, reinterpret_cast<const xmlChar
*>("id"));
166 if (!(xmlStrcmp(UriValue
, reinterpret_cast<const xmlChar
*>(pUIItemID
))))
167 changeNodeValue(pNodePtr
, pProperty
, pValue
);
170 searchNodeAndAttribute(pNodePtr
, pUIItemID
, pProperty
, pValue
);
172 pNodePtr
= pNodePtr
->next
;
176 static xmlDocPtr
notebookbarXMLParser(const OString
& rDocName
, const OString
& rUIItemID
,
177 const OString
& rProperty
, const OString
& rValue
)
179 xmlDocPtr pDocPtr
= xmlParseFile(rDocName
.getStr());
180 xmlNodePtr pNodePtr
= xmlDocGetRootElement(pDocPtr
);
181 searchNodeAndAttribute(pNodePtr
, rUIItemID
.getStr(), rProperty
.getStr(), rValue
.getStr());
185 void CustomNotebookbarGenerator::modifyCustomizedUIFile(const Sequence
<OUString
>& sUIItemProperties
)
187 OString sCustomizedUIPath
= getSystemPath(getCustomizedUIPath());
188 for (auto const& aValue
: sUIItemProperties
)
190 std::vector
<OString
> aProperties(aUIPropertiesCount
);
191 for (sal_Int32 aIndex
= 0; aIndex
< aUIPropertiesCount
; aIndex
++)
193 sal_Int32 nPos
= aIndex
;
194 std::u16string_view sToken
= o3tl::getToken(aValue
, nPos
, ',', nPos
);
195 aProperties
[aIndex
] = OUStringToOString(sToken
, RTL_TEXTENCODING_UTF8
);
197 xmlDocPtr doc
= notebookbarXMLParser(sCustomizedUIPath
, aProperties
[0], aProperties
[1],
202 xmlSaveFormatFile(sCustomizedUIPath
.getStr(), doc
, 1);
208 void CustomNotebookbarGenerator::getFileNameAndAppName(OUString
& sAppName
,
209 OUString
& sNotebookbarUIFileName
)
211 SfxViewFrame
* pFrame
= SfxViewFrame::Current();
215 const auto xContext
= comphelper::getProcessComponentContext();
216 utl::OConfigurationTreeRoot
aRoot(xContext
, "org.openoffice.Office.UI.ToolbarMode/", false);
217 const Reference
<frame::XFrame
>& xFrame
= pFrame
->GetFrame().GetFrameInterface();
218 const Reference
<frame::XModuleManager
> xModuleManager
= frame::ModuleManager::create(xContext
);
220 vcl::EnumContext::Application eApp
221 = vcl::EnumContext::GetApplicationEnum(xModuleManager
->identify(xFrame
));
222 OUString
sActiveAppName(lcl_activeAppName(eApp
));
223 sAppName
= lcl_getAppName(eApp
);
224 const Any aValue
= aRoot
.getNodeValue(sActiveAppName
);
225 aValue
>>= sNotebookbarUIFileName
;
228 void CustomNotebookbarGenerator::createCustomizedUIFile()
230 OUString sUserUIDir
= getUIDirPath();
231 OUString sOriginalUIPath
= getOriginalUIPath();
232 OUString sCustomizedUIPath
= getCustomizedUIPath();
234 sal_uInt32 nflag
= osl_File_OpenFlag_Read
| osl_File_OpenFlag_Write
;
235 osl::Directory
aDirectory(sUserUIDir
);
236 if (aDirectory
.open() != osl::FileBase::E_None
)
237 osl::Directory::create(sUserUIDir
, nflag
);
239 SAL_WARN("cui.customnotebookbar",
240 "Cannot create the directory or directory was present :" << sUserUIDir
);
242 osl::File
aFile(sCustomizedUIPath
);
243 if (aFile
.open(nflag
) != osl::FileBase::E_None
)
244 osl::File::copy(sOriginalUIPath
, sCustomizedUIPath
);
246 SAL_WARN("cui.customnotebookbar",
247 "Cannot copy the file or file was present :" << sCustomizedUIPath
);
250 Sequence
<OUString
> CustomNotebookbarGenerator::getCustomizedUIItem(OUString sNotebookbarConfigType
)
252 OUString aPath
= getAppNameRegistryPath();
253 const utl::OConfigurationTreeRoot
aAppNode(::comphelper::getProcessComponentContext(), aPath
,
256 const utl::OConfigurationNode aModesNode
= aAppNode
.openNode("Modes");
257 const utl::OConfigurationNode
aModeNode(aModesNode
.openNode(sNotebookbarConfigType
));
258 const Any aValue
= aModeNode
.getNodeValue("UIItemProperties");
259 Sequence
<OUString
> aValues
;
264 void CustomNotebookbarGenerator::setCustomizedUIItem(Sequence
<OUString
> sUIItemProperties
,
265 OUString sNotebookbarConfigType
)
267 OUString aPath
= getAppNameRegistryPath();
268 const utl::OConfigurationTreeRoot
aAppNode(::comphelper::getProcessComponentContext(), aPath
,
270 const utl::OConfigurationNode aModesNode
= aAppNode
.openNode("Modes");
271 const utl::OConfigurationNode
aModeNode(aModesNode
.openNode(sNotebookbarConfigType
));
273 css::uno::Any
aUIItemProperties(sUIItemProperties
);
274 aModeNode
.setNodeValue("UIItemProperties", aUIItemProperties
);
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */