LibreOffice Module cui (master) 1
CustomNotebookbarGenerator.cxx
Go to the documentation of this file.
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.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21#include <rtl/bootstrap.hxx>
22#include <config_folders.h>
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>
31#include <libxml/parser.h>
32#include <o3tl/string_view.hxx>
33
34#define aUIPropertiesCount 3
35
36using namespace css;
37
39
41{
42 switch (eApp)
43 {
45 return "ActiveWriter";
47 return "ActiveCalc";
49 return "ActiveImpress";
51 return "ActiveDraw";
52 default:
53 return OUString();
54 }
55}
56
58{
59 switch (eApp)
60 {
62 return "Writer";
64 return "Calc";
66 return "Impress";
68 return "Draw";
69 default:
70 return OUString();
71 }
72}
73
74static OUString getAppNameRegistryPath()
75{
77 const Reference<frame::XFrame>& xFrame
79 const Reference<frame::XModuleManager> xModuleManager
80 = frame::ModuleManager::create(::comphelper::getProcessComponentContext());
81 eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
82
83 OUString sAppName(lcl_getAppName(eApp));
84 return "org.openoffice.Office.UI.ToolbarMode/Applications/" + sAppName;
85}
86
87static OUString customizedUIPathBuffer()
88{
89 OUString sDirPath("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE(
90 "bootstrap") ":UserInstallation}/user/config/soffice.cfg/");
91 rtl::Bootstrap::expandMacros(sDirPath);
92 return sDirPath;
93}
94
96{
97 OUString sAppName, sNotebookbarUIFileName;
98 CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName);
99 return customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/"
100 + sNotebookbarUIFileName;
101}
102
104{
105 OUString sAppName, sNotebookbarUIFileName;
106 CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName);
107 return AllSettings::GetUIRootDir() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/"
108 + sNotebookbarUIFileName;
109}
110
111static OUString getUIDirPath()
112{
113 OUString sAppName, sNotebookbarUIFileName;
114 CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName);
115 OUString sUIDirPath
116 = customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/";
117 return sUIDirPath;
118}
119
120OString CustomNotebookbarGenerator::getSystemPath(OUString const& sURL)
121{
122 if (sURL.isEmpty())
123 return OString();
124 OUString sSystemPathSettings;
125 if (osl_getSystemPathFromFileURL(sURL.pData, &sSystemPathSettings.pData) != osl_File_E_None)
126 {
127 SAL_WARN("cui.customnotebookbar", "Cannot get system path for :" << sURL);
128 return OString();
129 }
130 OString osSystemPathSettings
131 = OUStringToOString(sSystemPathSettings, osl_getThreadTextEncoding());
132 return osSystemPathSettings;
133}
134
135static void changeNodeValue(xmlNode* pNodePtr, const char* pProperty, const char* pValue)
136{
137 pNodePtr = pNodePtr->xmlChildrenNode;
138 while (pNodePtr)
139 {
140 if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast<const xmlChar*>("property"))))
141 {
142 xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast<const xmlChar*>("name"));
143 if (!(xmlStrcmp(UriValue, reinterpret_cast<const xmlChar*>(pProperty))))
144 xmlNodeSetContent(pNodePtr, reinterpret_cast<const xmlChar*>(pValue));
145 xmlFree(UriValue);
146 break;
147 }
148 pNodePtr = pNodePtr->next;
149 }
150}
151
152static void searchNodeAndAttribute(xmlNode* pNodePtr, const char* pUIItemID, const char* pProperty,
153 const char* pValue)
154{
155 pNodePtr = pNodePtr->xmlChildrenNode;
156 while (pNodePtr)
157 {
158 if (pNodePtr->type == XML_ELEMENT_NODE)
159 {
160 if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast<const xmlChar*>("object"))))
161 {
162 xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast<const xmlChar*>("id"));
163 if (!(xmlStrcmp(UriValue, reinterpret_cast<const xmlChar*>(pUIItemID))))
164 changeNodeValue(pNodePtr, pProperty, pValue);
165 xmlFree(UriValue);
166 }
167 searchNodeAndAttribute(pNodePtr, pUIItemID, pProperty, pValue);
168 }
169 pNodePtr = pNodePtr->next;
170 }
171}
172
173static xmlDocPtr notebookbarXMLParser(const OString& rDocName, const OString& rUIItemID,
174 const OString& rProperty, const OString& rValue)
175{
176 xmlDocPtr pDocPtr = xmlParseFile(rDocName.getStr());
177 xmlNodePtr pNodePtr = xmlDocGetRootElement(pDocPtr);
178 searchNodeAndAttribute(pNodePtr, rUIItemID.getStr(), rProperty.getStr(), rValue.getStr());
179 return pDocPtr;
180}
181
182void CustomNotebookbarGenerator::modifyCustomizedUIFile(const Sequence<OUString>& sUIItemProperties)
183{
184 OString sCustomizedUIPath = getSystemPath(getCustomizedUIPath());
185 for (auto const& aValue : sUIItemProperties)
186 {
187 std::vector<OString> aProperties(aUIPropertiesCount);
188 for (sal_Int32 aIndex = 0; aIndex < aUIPropertiesCount; aIndex++)
189 {
190 sal_Int32 nPos = aIndex;
191 std::u16string_view sToken = o3tl::getToken(aValue, nPos, ',', nPos);
192 aProperties[aIndex] = OUStringToOString(sToken, RTL_TEXTENCODING_UTF8);
193 }
194 xmlDocPtr doc = notebookbarXMLParser(sCustomizedUIPath, aProperties[0], aProperties[1],
195 aProperties[2]);
196
197 if (doc != nullptr)
198 {
199 xmlSaveFormatFile(sCustomizedUIPath.getStr(), doc, 1);
200 xmlFreeDoc(doc);
201 }
202 }
203}
204
206 OUString& sNotebookbarUIFileName)
207{
209 if (!pFrame)
210 return;
211
212 const auto xContext = comphelper::getProcessComponentContext();
213 utl::OConfigurationTreeRoot aRoot(xContext, "org.openoffice.Office.UI.ToolbarMode/", false);
214 const Reference<frame::XFrame>& xFrame = pFrame->GetFrame().GetFrameInterface();
215 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create(xContext);
216
218 = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
219 OUString sActiveAppName(lcl_activeAppName(eApp));
220 sAppName = lcl_getAppName(eApp);
221 const Any aValue = aRoot.getNodeValue(sActiveAppName);
222 aValue >>= sNotebookbarUIFileName;
223}
224
226{
227 OUString sUserUIDir = getUIDirPath();
228 OUString sOriginalUIPath = getOriginalUIPath();
229 OUString sCustomizedUIPath = getCustomizedUIPath();
230
231 sal_uInt32 nflag = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write;
232 osl::Directory aDirectory(sUserUIDir);
233 if (aDirectory.open() != osl::FileBase::E_None)
234 osl::Directory::create(sUserUIDir, nflag);
235 else
236 SAL_WARN("cui.customnotebookbar",
237 "Cannot create the directory or directory was present :" << sUserUIDir);
238
239 osl::File aFile(sCustomizedUIPath);
240 if (aFile.open(nflag) != osl::FileBase::E_None)
241 osl::File::copy(sOriginalUIPath, sCustomizedUIPath);
242 else
243 SAL_WARN("cui.customnotebookbar",
244 "Cannot copy the file or file was present :" << sCustomizedUIPath);
245}
246
247Sequence<OUString> CustomNotebookbarGenerator::getCustomizedUIItem(OUString sNotebookbarConfigType)
248{
249 OUString aPath = getAppNameRegistryPath();
250 const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath,
251 false);
252
253 const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes");
254 const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType));
255 const Any aValue = aModeNode.getNodeValue("UIItemProperties");
256 Sequence<OUString> aValues;
257 aValue >>= aValues;
258 return aValues;
259}
260
261void CustomNotebookbarGenerator::setCustomizedUIItem(Sequence<OUString> sUIItemProperties,
262 OUString sNotebookbarConfigType)
263{
264 OUString aPath = getAppNameRegistryPath();
265 const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath,
266 true);
267 const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes");
268 const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType));
269
270 css::uno::Any aUIItemProperties(sUIItemProperties);
271 aModeNode.setNodeValue("UIItemProperties", aUIItemProperties);
272 aAppNode.commit();
273}
274
275/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static void searchNodeAndAttribute(xmlNode *pNodePtr, const char *pUIItemID, const char *pProperty, const char *pValue)
static void changeNodeValue(xmlNode *pNodePtr, const char *pProperty, const char *pValue)
static OUString getAppNameRegistryPath()
static xmlDocPtr notebookbarXMLParser(const OString &rDocName, const OString &rUIItemID, const OString &rProperty, const OString &rValue)
#define aUIPropertiesCount
static OUString getUIDirPath()
static OUString customizedUIPathBuffer()
static OUString lcl_activeAppName(vcl::EnumContext::Application eApp)
static OUString lcl_getAppName(vcl::EnumContext::Application eApp)
PropertiesInfo aProperties
static OUString GetUIRootDir()
static void setCustomizedUIItem(Sequence< OUString > sUIItemProperties, OUString sNotebookbarConfigType)
static void getFileNameAndAppName(OUString &sAppName, OUString &sNotebookbarUIFileName)
static OString getSystemPath(OUString const &sURL)
static void modifyCustomizedUIFile(const Sequence< OUString > &sUIItemProperties)
static Sequence< OUString > getCustomizedUIItem(OUString sNotebookbarConfigType)
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
static SfxViewFrame * Current()
SfxFrame & GetFrame() const
css::uno::Any getNodeValue(const OUString &_rPath) const noexcept
bool setNodeValue(const OUString &_rPath, const css::uno::Any &_rValue) const noexcept
OConfigurationNode openNode(const OUString &_rPath) const noexcept
bool commit() const noexcept
static Application GetApplicationEnum(const OUString &rsApplicationName)
#define SAL_CONFIGFILE(name)
std::deque< AttacherIndex_Impl > aIndex
sal_uInt16 nPos
#define SAL_WARN(area, stream)
Reference< XComponentContext > getProcessComponentContext()
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Reference< XFrame > xFrame