Use COMReference to handle COM pointers in CreateShortcut
[LibreOffice.git] / cui / source / customize / CustomNotebookbarGenerator.cxx
blobac2c18d5c238f27be0160e745748d4850403c25c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
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
36 using namespace css;
38 CustomNotebookbarGenerator::CustomNotebookbarGenerator() {}
40 static OUString lcl_activeAppName(vcl::EnumContext::Application eApp)
42 switch (eApp)
44 case vcl::EnumContext::Application::Writer:
45 return u"ActiveWriter"_ustr;
46 case vcl::EnumContext::Application::Calc:
47 return u"ActiveCalc"_ustr;
48 case vcl::EnumContext::Application::Impress:
49 return u"ActiveImpress"_ustr;
50 case vcl::EnumContext::Application::Draw:
51 return u"ActiveDraw"_ustr;
52 default:
53 return OUString();
57 static OUString lcl_getAppName(vcl::EnumContext::Application eApp)
59 switch (eApp)
61 case vcl::EnumContext::Application::Writer:
62 return u"Writer"_ustr;
63 case vcl::EnumContext::Application::Calc:
64 return u"Calc"_ustr;
65 case vcl::EnumContext::Application::Impress:
66 return u"Impress"_ustr;
67 case vcl::EnumContext::Application::Draw:
68 return u"Draw"_ustr;
69 default:
70 return OUString();
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(u"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE(
93 "bootstrap") ":UserInstallation}/user/config/soffice.cfg/"_ustr);
94 rtl::Bootstrap::expandMacros(sDirPath);
95 return 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);
118 OUString sUIDirPath
119 = customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/";
120 return sUIDirPath;
123 OString CustomNotebookbarGenerator::getSystemPath(OUString const& sURL)
125 if (sURL.isEmpty())
126 return OString();
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);
131 return OString();
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;
141 while (pNodePtr)
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));
148 xmlFree(UriValue);
149 break;
151 pNodePtr = pNodePtr->next;
155 static void searchNodeAndAttribute(xmlNode* pNodePtr, const char* pUIItemID, const char* pProperty,
156 const char* pValue)
158 pNodePtr = pNodePtr->xmlChildrenNode;
159 while (pNodePtr)
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);
168 xmlFree(UriValue);
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());
182 return pDocPtr;
185 void CustomNotebookbarGenerator::modifyCustomizedUIFile(const Sequence<OUString>& sUIItemProperties)
187 const OUString sUIPath = getCustomizedUIPath();
188 if (osl::File(sUIPath).open(osl_File_OpenFlag_Read) != osl::FileBase::E_None)
189 createCustomizedUIFile();
191 const OString sCustomizedUIPath = getSystemPath(sUIPath);
192 for (auto const& aValue : sUIItemProperties)
194 std::vector<OString> aProperties(aUIPropertiesCount);
195 for (sal_Int32 aIndex = 0; aIndex < aUIPropertiesCount; aIndex++)
197 sal_Int32 nPos = aIndex;
198 std::u16string_view sToken = o3tl::getToken(aValue, nPos, ',', nPos);
199 aProperties[aIndex] = OUStringToOString(sToken, RTL_TEXTENCODING_UTF8);
201 xmlDocPtr doc = notebookbarXMLParser(sCustomizedUIPath, aProperties[0], aProperties[1],
202 aProperties[2]);
204 if (doc != nullptr)
206 xmlSaveFormatFile(sCustomizedUIPath.getStr(), doc, 1);
207 xmlFreeDoc(doc);
212 void CustomNotebookbarGenerator::getFileNameAndAppName(OUString& sAppName,
213 OUString& sNotebookbarUIFileName)
215 SfxViewFrame* pFrame = SfxViewFrame::Current();
216 if (!pFrame)
217 return;
219 const auto& xContext = comphelper::getProcessComponentContext();
220 utl::OConfigurationTreeRoot aRoot(xContext, u"org.openoffice.Office.UI.ToolbarMode/"_ustr,
221 false);
222 const Reference<frame::XFrame>& xFrame = pFrame->GetFrame().GetFrameInterface();
223 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create(xContext);
225 vcl::EnumContext::Application eApp
226 = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
227 OUString sActiveAppName(lcl_activeAppName(eApp));
228 sAppName = lcl_getAppName(eApp);
229 const Any aValue = aRoot.getNodeValue(sActiveAppName);
230 aValue >>= sNotebookbarUIFileName;
233 void CustomNotebookbarGenerator::createCustomizedUIFile()
235 OUString sUserUIDir = getUIDirPath();
236 OUString sOriginalUIPath = getOriginalUIPath();
237 OUString sCustomizedUIPath = getCustomizedUIPath();
239 sal_uInt32 nflag = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write;
240 osl::Directory aDirectory(sUserUIDir);
241 if (aDirectory.open() != osl::FileBase::E_None)
242 osl::Directory::create(sUserUIDir, nflag);
243 else
244 SAL_WARN("cui.customnotebookbar",
245 "Cannot create the directory or directory was present :" << sUserUIDir);
247 osl::File aFile(sCustomizedUIPath);
248 if (aFile.open(nflag) != osl::FileBase::E_None)
249 osl::File::copy(sOriginalUIPath, sCustomizedUIPath);
250 else
251 SAL_WARN("cui.customnotebookbar",
252 "Cannot copy the file or file was present :" << sCustomizedUIPath);
255 Sequence<OUString>
256 CustomNotebookbarGenerator::getCustomizedUIItem(const OUString& sNotebookbarConfigType)
258 OUString aPath = getAppNameRegistryPath();
259 const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath,
260 false);
262 const utl::OConfigurationNode aModesNode = aAppNode.openNode(u"Modes"_ustr);
263 const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType));
264 const Any aValue = aModeNode.getNodeValue(u"UIItemProperties"_ustr);
265 Sequence<OUString> aValues;
266 aValue >>= aValues;
267 return aValues;
270 void CustomNotebookbarGenerator::setCustomizedUIItem(const Sequence<OUString>& rUIItemProperties,
271 const OUString& rNotebookbarConfigType)
273 OUString aPath = getAppNameRegistryPath();
274 const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath,
275 true);
276 const utl::OConfigurationNode aModesNode = aAppNode.openNode(u"Modes"_ustr);
277 const utl::OConfigurationNode aModeNode(aModesNode.openNode(rNotebookbarConfigType));
279 css::uno::Any aUIItemProperties(rUIItemProperties);
280 aModeNode.setNodeValue(u"UIItemProperties"_ustr, aUIItemProperties);
281 aAppNode.commit();
284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */