diff options
Diffstat (limited to 'cui/source/customize/CustomNotebookbarGenerator.cxx')
-rw-r--r-- | cui/source/customize/CustomNotebookbarGenerator.cxx | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/cui/source/customize/CustomNotebookbarGenerator.cxx b/cui/source/customize/CustomNotebookbarGenerator.cxx new file mode 100644 index 0000000000..ba5d881822 --- /dev/null +++ b/cui/source/customize/CustomNotebookbarGenerator.cxx @@ -0,0 +1,282 @@ +/* -*- 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 <comphelper/processfactory.hxx> +#include <rtl/bootstrap.hxx> +#include <config_folders.h> +#include <CustomNotebookbarGenerator.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <vcl/EnumContext.hxx> +#include <vcl/settings.hxx> +#include <sfx2/viewfrm.hxx> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <unotools/confignode.hxx> +#include <libxml/parser.h> +#include <o3tl/string_view.hxx> + +#define aUIPropertiesCount 3 + +using namespace css; + +CustomNotebookbarGenerator::CustomNotebookbarGenerator() {} + +static OUString lcl_activeAppName(vcl::EnumContext::Application eApp) +{ + switch (eApp) + { + case vcl::EnumContext::Application::Writer: + return "ActiveWriter"; + case vcl::EnumContext::Application::Calc: + return "ActiveCalc"; + case vcl::EnumContext::Application::Impress: + return "ActiveImpress"; + case vcl::EnumContext::Application::Draw: + return "ActiveDraw"; + default: + return OUString(); + } +} + +static OUString lcl_getAppName(vcl::EnumContext::Application eApp) +{ + switch (eApp) + { + case vcl::EnumContext::Application::Writer: + return "Writer"; + case vcl::EnumContext::Application::Calc: + return "Calc"; + case vcl::EnumContext::Application::Impress: + return "Impress"; + case vcl::EnumContext::Application::Draw: + return "Draw"; + default: + return OUString(); + } +} + +static OUString getAppNameRegistryPath() +{ + vcl::EnumContext::Application eApp = vcl::EnumContext::Application::Any; + + if (SfxViewFrame* pViewFrame = SfxViewFrame::Current()) + { + const Reference<frame::XFrame>& xFrame = pViewFrame->GetFrame().GetFrameInterface(); + const Reference<frame::XModuleManager> xModuleManager + = frame::ModuleManager::create(::comphelper::getProcessComponentContext()); + eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); + } + + OUString sAppName(lcl_getAppName(eApp)); + return "org.openoffice.Office.UI.ToolbarMode/Applications/" + sAppName; +} + +static OUString customizedUIPathBuffer() +{ + OUString sDirPath("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( + "bootstrap") ":UserInstallation}/user/config/soffice.cfg/"); + rtl::Bootstrap::expandMacros(sDirPath); + return sDirPath; +} + +OUString CustomNotebookbarGenerator::getCustomizedUIPath() +{ + OUString sAppName, sNotebookbarUIFileName; + CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); + return customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/" + + sNotebookbarUIFileName; +} + +OUString CustomNotebookbarGenerator::getOriginalUIPath() +{ + OUString sAppName, sNotebookbarUIFileName; + CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); + return AllSettings::GetUIRootDir() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/" + + sNotebookbarUIFileName; +} + +static OUString getUIDirPath() +{ + OUString sAppName, sNotebookbarUIFileName; + CustomNotebookbarGenerator::getFileNameAndAppName(sAppName, sNotebookbarUIFileName); + OUString sUIDirPath + = customizedUIPathBuffer() + "modules/s" + sAppName.toAsciiLowerCase() + "/ui/"; + return sUIDirPath; +} + +OString CustomNotebookbarGenerator::getSystemPath(OUString const& sURL) +{ + if (sURL.isEmpty()) + return OString(); + OUString sSystemPathSettings; + if (osl_getSystemPathFromFileURL(sURL.pData, &sSystemPathSettings.pData) != osl_File_E_None) + { + SAL_WARN("cui.customnotebookbar", "Cannot get system path for :" << sURL); + return OString(); + } + OString osSystemPathSettings + = OUStringToOString(sSystemPathSettings, osl_getThreadTextEncoding()); + return osSystemPathSettings; +} + +static void changeNodeValue(xmlNode* pNodePtr, const char* pProperty, const char* pValue) +{ + pNodePtr = pNodePtr->xmlChildrenNode; + while (pNodePtr) + { + if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast<const xmlChar*>("property")))) + { + xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast<const xmlChar*>("name")); + if (!(xmlStrcmp(UriValue, reinterpret_cast<const xmlChar*>(pProperty)))) + xmlNodeSetContent(pNodePtr, reinterpret_cast<const xmlChar*>(pValue)); + xmlFree(UriValue); + break; + } + pNodePtr = pNodePtr->next; + } +} + +static void searchNodeAndAttribute(xmlNode* pNodePtr, const char* pUIItemID, const char* pProperty, + const char* pValue) +{ + pNodePtr = pNodePtr->xmlChildrenNode; + while (pNodePtr) + { + if (pNodePtr->type == XML_ELEMENT_NODE) + { + if (!(xmlStrcmp(pNodePtr->name, reinterpret_cast<const xmlChar*>("object")))) + { + xmlChar* UriValue = xmlGetProp(pNodePtr, reinterpret_cast<const xmlChar*>("id")); + if (!(xmlStrcmp(UriValue, reinterpret_cast<const xmlChar*>(pUIItemID)))) + changeNodeValue(pNodePtr, pProperty, pValue); + xmlFree(UriValue); + } + searchNodeAndAttribute(pNodePtr, pUIItemID, pProperty, pValue); + } + pNodePtr = pNodePtr->next; + } +} + +static xmlDocPtr notebookbarXMLParser(const OString& rDocName, const OString& rUIItemID, + const OString& rProperty, const OString& rValue) +{ + xmlDocPtr pDocPtr = xmlParseFile(rDocName.getStr()); + xmlNodePtr pNodePtr = xmlDocGetRootElement(pDocPtr); + searchNodeAndAttribute(pNodePtr, rUIItemID.getStr(), rProperty.getStr(), rValue.getStr()); + return pDocPtr; +} + +void CustomNotebookbarGenerator::modifyCustomizedUIFile(const Sequence<OUString>& sUIItemProperties) +{ + const OUString sUIPath = getCustomizedUIPath(); + if (osl::File(sUIPath).open(osl_File_OpenFlag_Read) != osl::FileBase::E_None) + createCustomizedUIFile(); + + const OString sCustomizedUIPath = getSystemPath(sUIPath); + for (auto const& aValue : sUIItemProperties) + { + std::vector<OString> aProperties(aUIPropertiesCount); + for (sal_Int32 aIndex = 0; aIndex < aUIPropertiesCount; aIndex++) + { + sal_Int32 nPos = aIndex; + std::u16string_view sToken = o3tl::getToken(aValue, nPos, ',', nPos); + aProperties[aIndex] = OUStringToOString(sToken, RTL_TEXTENCODING_UTF8); + } + xmlDocPtr doc = notebookbarXMLParser(sCustomizedUIPath, aProperties[0], aProperties[1], + aProperties[2]); + + if (doc != nullptr) + { + xmlSaveFormatFile(sCustomizedUIPath.getStr(), doc, 1); + xmlFreeDoc(doc); + } + } +} + +void CustomNotebookbarGenerator::getFileNameAndAppName(OUString& sAppName, + OUString& sNotebookbarUIFileName) +{ + SfxViewFrame* pFrame = SfxViewFrame::Current(); + if (!pFrame) + return; + + const auto xContext = comphelper::getProcessComponentContext(); + utl::OConfigurationTreeRoot aRoot(xContext, "org.openoffice.Office.UI.ToolbarMode/", false); + const Reference<frame::XFrame>& xFrame = pFrame->GetFrame().GetFrameInterface(); + const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create(xContext); + + vcl::EnumContext::Application eApp + = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame)); + OUString sActiveAppName(lcl_activeAppName(eApp)); + sAppName = lcl_getAppName(eApp); + const Any aValue = aRoot.getNodeValue(sActiveAppName); + aValue >>= sNotebookbarUIFileName; +} + +void CustomNotebookbarGenerator::createCustomizedUIFile() +{ + OUString sUserUIDir = getUIDirPath(); + OUString sOriginalUIPath = getOriginalUIPath(); + OUString sCustomizedUIPath = getCustomizedUIPath(); + + sal_uInt32 nflag = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write; + osl::Directory aDirectory(sUserUIDir); + if (aDirectory.open() != osl::FileBase::E_None) + osl::Directory::create(sUserUIDir, nflag); + else + SAL_WARN("cui.customnotebookbar", + "Cannot create the directory or directory was present :" << sUserUIDir); + + osl::File aFile(sCustomizedUIPath); + if (aFile.open(nflag) != osl::FileBase::E_None) + osl::File::copy(sOriginalUIPath, sCustomizedUIPath); + else + SAL_WARN("cui.customnotebookbar", + "Cannot copy the file or file was present :" << sCustomizedUIPath); +} + +Sequence<OUString> CustomNotebookbarGenerator::getCustomizedUIItem(OUString sNotebookbarConfigType) +{ + OUString aPath = getAppNameRegistryPath(); + const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath, + false); + + const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes"); + const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType)); + const Any aValue = aModeNode.getNodeValue("UIItemProperties"); + Sequence<OUString> aValues; + aValue >>= aValues; + return aValues; +} + +void CustomNotebookbarGenerator::setCustomizedUIItem(Sequence<OUString> sUIItemProperties, + OUString sNotebookbarConfigType) +{ + OUString aPath = getAppNameRegistryPath(); + const utl::OConfigurationTreeRoot aAppNode(::comphelper::getProcessComponentContext(), aPath, + true); + const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes"); + const utl::OConfigurationNode aModeNode(aModesNode.openNode(sNotebookbarConfigType)); + + css::uno::Any aUIItemProperties(sUIItemProperties); + aModeNode.setNodeValue("UIItemProperties", aUIItemProperties); + aAppNode.commit(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |