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>
30 #include <unotools/confignode.hxx>
31 #include <libxml/parser.h>
32 #include <o3tl/string_view.hxx>
33 
34 #define aUIPropertiesCount 3
35 
36 using 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 
74 static 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 
87 static 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 
111 static 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 
120 OString 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 
135 static 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 
152 static 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 
173 static 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 
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 
248 {
249  OUString aPath = getAppNameRegistryPath();
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 
262  OUString sNotebookbarConfigType)
263 {
264  OUString aPath = getAppNameRegistryPath();
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: */
#define aUIPropertiesCount
static void getFileNameAndAppName(OUString &sAppName, OUString &sNotebookbarUIFileName)
static OUString getUIDirPath()
static void modifyCustomizedUIFile(const Sequence< OUString > &sUIItemProperties)
Reference< XFrame > xFrame
static xmlDocPtr notebookbarXMLParser(const OString &rDocName, const OString &rUIItemID, const OString &rProperty, const OString &rValue)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
static OUString customizedUIPathBuffer()
PropertiesInfo aProperties
SfxFrame & GetFrame() const
static void searchNodeAndAttribute(xmlNode *pNodePtr, const char *pUIItemID, const char *pProperty, const char *pValue)
static OUString lcl_getAppName(vcl::EnumContext::Application eApp)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
static OUString GetUIRootDir()
#define SAL_CONFIGFILE(name)
static OString getSystemPath(OUString const &sURL)
css::uno::Any getNodeValue(const OUString &_rPath) const noexcept
static OUString lcl_activeAppName(vcl::EnumContext::Application eApp)
OConfigurationNode openNode(const OUString &_rPath) const noexcept
static Application GetApplicationEnum(const OUString &rsApplicationName)
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
static Sequence< OUString > getCustomizedUIItem(OUString sNotebookbarConfigType)
static OUString getAppNameRegistryPath()
static SfxViewFrame * Current()
std::deque< AttacherIndex_Impl > aIndex
Reference< XComponentContext > getProcessComponentContext()
static void changeNodeValue(xmlNode *pNodePtr, const char *pProperty, const char *pValue)
#define SAL_WARN(area, stream)
static void setCustomizedUIItem(Sequence< OUString > sUIItemProperties, OUString sNotebookbarConfigType)
sal_uInt16 nPos
bool commit() const noexcept