LibreOffice Module desktop (master) 1
migration.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
20#include <sal/config.h>
21
22#include <algorithm>
23#include <iterator>
24#include <map>
25#include <set>
26
27#include <migration.hxx>
28#include "migration_impl.hxx"
29
30#include <sal/log.hxx>
35#include <rtl/uri.hxx>
36#include <i18nlangtag/lang.h>
38#include <tools/urlobj.hxx>
39#include <officecfg/Office/UI.hxx>
40#include <osl/file.hxx>
41#include <osl/security.hxx>
43
44#include <com/sun/star/configuration/Update.hpp>
45#include <com/sun/star/configuration/theDefaultProvider.hpp>
46#include <com/sun/star/container/XNameContainer.hpp>
47#include <com/sun/star/task/XJob.hpp>
48#include <com/sun/star/beans/NamedValue.hpp>
49#include <com/sun/star/beans/XPropertySet.hpp>
50#include <com/sun/star/util/XRefreshable.hpp>
51#include <com/sun/star/util/XChangesBatch.hpp>
52#include <com/sun/star/embed/ElementModes.hpp>
53#include <com/sun/star/embed/FileSystemStorageFactory.hpp>
54#include <com/sun/star/embed/XStorage.hpp>
55#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
56#include <com/sun/star/ui/UIConfigurationManager.hpp>
57#include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
59
60using namespace osl;
61using namespace com::sun::star::task;
62using namespace com::sun::star::lang;
63using namespace com::sun::star::beans;
64using namespace com::sun::star::util;
65using namespace com::sun::star::container;
66using com::sun::star::uno::Exception;
67using namespace com::sun::star;
68
69
70namespace desktop
71{
72
73constexpr OUStringLiteral ITEM_DESCRIPTOR_COMMANDURL = u"CommandURL";
74constexpr OUStringLiteral ITEM_DESCRIPTOR_CONTAINER = u"ItemDescriptorContainer";
75constexpr OUStringLiteral ITEM_DESCRIPTOR_LABEL = u"Label";
76
77static OUString mapModuleShortNameToIdentifier(std::u16string_view sShortName)
78{
79 OUString sIdentifier;
80
81 if ( sShortName == u"StartModule" )
82 sIdentifier = "com.sun.star.frame.StartModule";
83
84 else if ( sShortName == u"swriter" )
85 sIdentifier = "com.sun.star.text.TextDocument";
86
87 else if ( sShortName == u"scalc" )
88 sIdentifier = "com.sun.star.sheet.SpreadsheetDocument";
89
90 else if ( sShortName == u"sdraw" )
91 sIdentifier = "com.sun.star.drawing.DrawingDocument";
92
93 else if ( sShortName == u"simpress" )
94 sIdentifier = "com.sun.star.presentation.PresentationDocument";
95
96 else if ( sShortName == u"smath" )
97 sIdentifier = "com.sun.star.formula.FormulaProperties";
98
99 else if ( sShortName == u"schart" )
100 sIdentifier = "com.sun.star.chart2.ChartDocument";
101
102 else if ( sShortName == u"BasicIDE" )
103 sIdentifier = "com.sun.star.script.BasicIDE";
104
105 else if ( sShortName == u"dbapp" )
106 sIdentifier = "com.sun.star.sdb.OfficeDatabaseDocument";
107
108 else if ( sShortName == u"sglobal" )
109 sIdentifier = "com.sun.star.text.GlobalDocument";
110
111 else if ( sShortName == u"sweb" )
112 sIdentifier = "com.sun.star.text.WebDocument";
113
114 else if ( sShortName == u"swxform" )
115 sIdentifier = "com.sun.star.xforms.XMLFormDocument";
116
117 else if ( sShortName == u"sbibliography" )
118 sIdentifier = "com.sun.star.frame.Bibliography";
119
120 return sIdentifier;
121}
122
124{
125 OUString aStr = m_aInfo.userdata + "/MIGRATED4";
126 File aFile(aStr);
127 // create migration stamp, and/or check its existence
128 bool bRet = aFile.open (osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock) == FileBase::E_EXIST;
129 SAL_INFO( "desktop.migration", "File '" << aStr << "' exists? " << bRet );
130 return bRet;
131}
132
134{
135 bool bRet = false;
136
140 // m_aInfo is now set to the preferred migration source
141 if ( nIndex >= 0 ) {
142 if (alreadyMigrated())
143 return false;
145 }
146
147 bRet = !m_aInfo.userdata.isEmpty();
148 }
149
150 SAL_INFO( "desktop.migration", "Migration " << ( bRet ? "needed" : "not required" ) );
151
152 return bRet;
153}
154
156{
157 MigrationImpl aImpl;
158
159 if (! aImpl.initializeMigration() )
160 return;
161
162 bool bResult = false;
163 try {
164 bResult = aImpl.doMigration();
165 } catch (const Exception&) {
166 TOOLS_WARN_EXCEPTION( "desktop", "doMigration()");
167 }
168 OSL_ENSURE(bResult, "Migration has not been successful");
169}
170
172{
173}
174
176{
177}
178
179// The main entry point for migrating settings
181{
182 // compile file list for migration
184
185 bool result = false;
186 try {
187 NewVersionUIInfo aNewVersionUIInfo;
188 std::vector< MigrationModuleInfo > vModulesInfo = detectUIChangesForAllModules();
189 aNewVersionUIInfo.init(vModulesInfo);
190
191 copyFiles();
192
193 static constexpr OUStringLiteral sMenubarResourceURL(u"private:resource/menubar/menubar");
194 static constexpr OUStringLiteral sToolbarResourcePre(u"private:resource/toolbar/");
195 for (MigrationModuleInfo & i : vModulesInfo) {
196 OUString sModuleIdentifier = mapModuleShortNameToIdentifier(i.sModuleShortName);
197 if (sModuleIdentifier.isEmpty())
198 continue;
199
200
201 OUString aOldCfgDataPath = m_aInfo.userdata + "/user/config/soffice.cfg/modules/" + i.sModuleShortName;
202 uno::Sequence< uno::Any > lArgs {uno::Any(aOldCfgDataPath), uno::Any(embed::ElementModes::READ)};
203
206 uno::Reference< embed::XStorage > xModules(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
208
209 if ( xModules.is() ) {
210 xOldCfgManager->setStorage( xModules );
211 xOldCfgManager->reload();
212 }
213
214 uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(i.sModuleShortName);
215
216 if (i.bHasMenubar) {
217 uno::Reference< container::XIndexContainer > xOldVersionMenuSettings(xOldCfgManager->getSettings(sMenubarResourceURL, true), uno::UNO_QUERY);
218 uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(i.sModuleShortName);
219 compareOldAndNewConfig(OUString(), xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL);
220 mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL);
221 }
222
223 sal_Int32 nToolbars = i.m_vToolbars.size();
224 if (nToolbars >0) {
225 for (sal_Int32 j=0; j<nToolbars; ++j) {
226 OUString sToolbarName = i.m_vToolbars[j];
227 OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
228
229 uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings(xOldCfgManager->getSettings(sToolbarResourceURL, true), uno::UNO_QUERY);
230 uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(i.sModuleShortName, sToolbarName);
231 compareOldAndNewConfig(OUString(), xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL);
232 mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL);
233 }
234 }
235
237 }
238
239 // execute the migration items from Setup.xcu
240 copyConfig();
241
242 // execute custom migration services from Setup.xcu
243 // and refresh the cache
244 runServices();
246 configuration::theDefaultProvider::get(comphelper::getProcessComponentContext()),
247 uno::UNO_QUERY_THROW)->refresh();
248
249 result = true;
250 } catch (const css::uno::Exception &) {
252 "desktop.migration",
253 "ignored Exception while migrating from version \"" << m_aInfo.productname
254 << "\" data \"" << m_aInfo.userdata << "\"");
255 }
256
257 // prevent running the migration multiple times
259 return result;
260}
261
263{
264 try {
265 uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW);
266 aPropertySet->setPropertyValue("MigrationCompleted", uno::Any(true));
267 uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
268 } catch (...) {
269 // fail silently
270 }
271}
272
274{
275 bool bMigrationCompleted = false;
276 try {
278 getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW);
279 aPropertySet->getPropertyValue("MigrationCompleted") >>= bMigrationCompleted;
280
281 if( !bMigrationCompleted && getenv("SAL_DISABLE_USERMIGRATION" ) ) {
282 // migration prevented - fake its success
284 bMigrationCompleted = true;
285 }
286 } catch (const Exception&) {
287 // just return false...
288 }
289 SAL_INFO( "desktop.migration", "Migration " << ( bMigrationCompleted ? "already completed" : "not done" ) );
290
291 return bMigrationCompleted;
292}
293
294static void insertSorted(migrations_available& rAvailableMigrations, supported_migration const & aSupportedMigration)
295{
296 migrations_available::iterator pIter = std::find_if(rAvailableMigrations.begin(), rAvailableMigrations.end(),
297 [&aSupportedMigration](const supported_migration& rMigration) { return rMigration.nPriority < aSupportedMigration.nPriority; });
298 if (pIter != rAvailableMigrations.end())
299 rAvailableMigrations.insert(pIter, aSupportedMigration );
300 else
301 rAvailableMigrations.push_back( aSupportedMigration );
302}
303
305{
306 // get supported version names
307 uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_SET_THROW);
308 const uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames();
309
310 static constexpr OUStringLiteral aVersionIdentifiers( u"VersionIdentifiers" );
311 static constexpr OUStringLiteral aPriorityIdentifier( u"Priority" );
312
313 for (OUString const & supportedVersion :seqSupportedVersions) {
314 sal_Int32 nPriority( 0 );
315 uno::Sequence< OUString > seqVersions;
316 uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(supportedVersion), uno::UNO_QUERY_THROW );
317 xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions;
318 xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority;
319
320 supported_migration aSupportedMigration;
321 aSupportedMigration.name = supportedVersion;
322 aSupportedMigration.nPriority = nPriority;
323 for (OUString const & s : std::as_const(seqVersions))
324 aSupportedMigration.supported_versions.push_back(s.trim());
325 insertSorted( rAvailableMigrations, aSupportedMigration );
326 SAL_INFO( "desktop.migration", " available migration '" << aSupportedMigration.name << "'" );
327 }
328}
329
331{
332 // get migration access
333 uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_SET_THROW);
334 uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW );
335
336 // get migration description from org.openoffice.Setup/Migration
337 // and build vector of migration steps
338 uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName("MigrationSteps"), uno::UNO_QUERY_THROW);
341 migrations_vr vrMigrations(new migrations_v);
342 const css::uno::Sequence<OUString> aMigrationSteps = theNameAccess->getElementNames();
343 for (const OUString& rMigrationStep : aMigrationSteps) {
344 // get current migration step
345 theNameAccess->getByName(rMigrationStep) >>= tmpAccess;
346 migration_step tmpStep;
347
348 // read included files from current step description
349 if (tmpAccess->getByName("IncludedFiles") >>= tmpSeq) {
350 for (const OUString& rSeqEntry : std::as_const(tmpSeq))
351 tmpStep.includeFiles.push_back(rSeqEntry);
352 }
353
354 // excluded files...
355 if (tmpAccess->getByName("ExcludedFiles") >>= tmpSeq) {
356 for (const OUString& rSeqEntry : std::as_const(tmpSeq))
357 tmpStep.excludeFiles.push_back(rSeqEntry);
358 }
359
360 // included nodes...
361 if (tmpAccess->getByName("IncludedNodes") >>= tmpSeq) {
362 for (const OUString& rSeqEntry : std::as_const(tmpSeq))
363 tmpStep.includeConfig.push_back(rSeqEntry);
364 }
365
366 // excluded nodes...
367 if (tmpAccess->getByName("ExcludedNodes") >>= tmpSeq) {
368 for (const OUString& rSeqEntry : std::as_const(tmpSeq))
369 tmpStep.excludeConfig.push_back(rSeqEntry);
370 }
371
372 // excluded extensions...
373 if (tmpAccess->getByName("ExcludedExtensions") >>= tmpSeq) {
374 for (const OUString& rSeqEntry : std::as_const(tmpSeq))
375 tmpStep.excludeExtensions.push_back(rSeqEntry);
376 }
377
378 // generic service
379 tmpAccess->getByName("MigrationService") >>= tmpStep.service;
380
381 vrMigrations->push_back(tmpStep);
382 }
383 return vrMigrations;
384}
385
386static FileBase::RC _checkAndCreateDirectory(INetURLObject const & dirURL)
387{
389 if (result == FileBase::E_NOENT) {
390 INetURLObject baseURL(dirURL);
391 baseURL.removeSegment();
394 } else
395 return result;
396}
397
398#if defined UNX && ! defined MACOSX
399
400const char XDG_CONFIG_PART[] = "/.config/";
401
402OUString MigrationImpl::preXDGConfigDir(const OUString& rConfigDir)
403{
404 OUString aPreXDGConfigPath;
405 const char* pXDGCfgHome = getenv("XDG_CONFIG_HOME");
406
407 // cater for XDG_CONFIG_HOME change
408 // If XDG_CONFIG_HOME is set then we;
409 // assume the user knows what they are doing ( room for improvement here, we could
410 // of course search the default config dir etc. also - but this is more complex,
411 // we would need to weigh results from the current config dir against matches in
412 // the 'old' config dir etc. ) - currently we just use the returned config dir.
413 // If XDG_CONFIG_HOME is NOT set;
414 // assume then we should now using the default $HOME/.config config location for
415 // our user profiles, however *all* previous libreoffice and openoffice.org
416 // configurations will be in the 'old' config directory and that's where we need
417 // to search - we convert the returned config dir to the 'old' dir
418 if ( !pXDGCfgHome && rConfigDir.endsWith( XDG_CONFIG_PART ) )
419 // remove trailing '.config/' but leave the terminating '/'
420 aPreXDGConfigPath = rConfigDir.copy( 0, rConfigDir.getLength() - sizeof( XDG_CONFIG_PART ) + 2 );
421 else
422 aPreXDGConfigPath = rConfigDir;
423
424 // the application-specific config dir is no longer prefixed by '.' because it is hidden under ".config"
425 // we have to add the '.' for the pre-XDG directory names
426 aPreXDGConfigPath += ".";
427
428 return aPreXDGConfigPath;
429}
430#endif
431
433 install_info& aInfo,
434 std::u16string_view rConfigDir,
435 const OUString& rVersion)
436{
437 OUString url(INetURLObject(rConfigDir).GetMainURL(INetURLObject::DecodeMechanism::NONE));
438 osl::DirectoryItem item;
439 osl::FileStatus stat(osl_FileStatus_Mask_Type);
440
441 if (osl::DirectoryItem::get(url, item) == osl::FileBase::E_None
442 && item.getFileStatus(stat) == osl::FileBase::E_None
443 && stat.getFileType() == osl::FileStatus::Directory) {
444 aInfo.userdata = url;
445 aInfo.productname = rVersion;
446 }
447}
448
450{
451
452 OUString aTopConfigDir;
453 osl::Security().getConfigDir( aTopConfigDir );
454 if ( !aTopConfigDir.isEmpty() && aTopConfigDir[ aTopConfigDir.getLength()-1 ] != '/' )
455 aTopConfigDir += "/";
456
457#if defined UNX && ! defined MACOSX
458 OUString aPreXDGTopConfigDir = preXDGConfigDir(aTopConfigDir);
459#endif
460
461 install_info aInfo;
462 for (auto const& elem : rVersions)
463 {
464 OUString aVersion, aProfileName;
465 sal_Int32 nSeparatorIndex = elem.indexOf('=');
466 if ( nSeparatorIndex != -1 ) {
467 aVersion = elem.copy( 0, nSeparatorIndex );
468 aProfileName = elem.copy( nSeparatorIndex+1 );
469 }
470
471 if ( !aVersion.isEmpty() && !aProfileName.isEmpty() &&
472 ( aInfo.userdata.isEmpty() ||
473 aProfileName.equalsIgnoreAsciiCase(
475 setInstallInfoIfExist(aInfo, Concat2View(aTopConfigDir + aProfileName), aVersion);
476#if defined UNX && ! defined MACOSX
477 //try preXDG path if the new one does not exist
478 if ( aInfo.userdata.isEmpty())
479 setInstallInfoIfExist(aInfo, Concat2View(aPreXDGTopConfigDir + aProfileName), aVersion);
480#endif
481 }
482 }
483
484 return aInfo;
485}
486
488{
489 sal_Int32 nIndex( -1 );
490 sal_Int32 i( 0 );
491
492 for (auto const& availableMigration : rAvailableMigrations)
493 {
494 install_info aInstallInfo = findInstallation(availableMigration.supported_versions);
495 if (!aInstallInfo.productname.isEmpty() ) {
496 m_aInfo = aInstallInfo;
497 nIndex = i;
498 break;
499 }
500 ++i;
501 }
502
503 SAL_INFO( "desktop.migration", " preferred migration is from product '" << m_aInfo.productname << "'");
504 SAL_INFO( "desktop.migration", " and settings directory '" << m_aInfo.userdata << "'");
505
506 return nIndex;
507}
508
510{
511 using namespace utl;
512 strings_vr vrResult(new strings_v);
513 for (auto const& pattern : vPatterns)
514 {
515 // find matches for this pattern in input set
516 // and copy them to the result
517 SearchParam param(pattern, SearchParam::SearchType::Regexp);
518 TextSearch ts(param, LANGUAGE_DONTKNOW);
519 sal_Int32 start = 0;
520 sal_Int32 end = 0;
521 for (auto const& elem : vSet)
522 {
523 end = elem.getLength();
524 if (ts.SearchForward(elem, &start, &end))
525 vrResult->push_back(elem);
526 }
527 }
528 return vrResult;
529}
530
531strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const
532{
533 strings_vr vrResult(new strings_v);
534
535 // get sub dirs
536 Directory dir(baseURL);
537 if (dir.open() == FileBase::E_None) {
538 strings_v vSubDirs;
539 strings_vr vrSubResult;
540
541 // work through directory contents...
542 DirectoryItem item;
543 FileStatus fs(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL);
544 while (dir.getNextItem(item) == FileBase::E_None) {
545 if (item.getFileStatus(fs) == FileBase::E_None) {
546 if (fs.getFileType() == FileStatus::Directory)
547 vSubDirs.push_back(fs.getFileURL());
548 else
549 vrResult->push_back(fs.getFileURL());
550 }
551 }
552
553 // recurse subfolders
554 for (auto const& subDir : vSubDirs)
555 {
556 vrSubResult = getAllFiles(subDir);
557 vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end());
558 }
559 }
560 return vrResult;
561}
562
563namespace
564{
565
566// removes elements of vector 2 in vector 1
567strings_v subtract(strings_v && a, strings_v && b)
568{
569 std::sort(a.begin(), a.end());
570 strings_v::iterator ae(std::unique(a.begin(), a.end()));
571 std::sort(b.begin(), b.end());
572 strings_v::iterator be(std::unique(b.begin(), b.end()));
573 strings_v c;
574 std::set_difference(a.begin(), ae, b.begin(), be, std::back_inserter(c));
575 return c;
576}
577
578}
579
581{
582
583 strings_vr vrResult(new strings_v);
584
585 // get a list of all files:
587
588 // get a file list result for each migration step
589 for (auto const& rMigration : *m_vrMigrations)
590 {
591 strings_vr vrInclude = applyPatterns(*vrFiles, rMigration.includeFiles);
592 strings_vr vrExclude = applyPatterns(*vrFiles, rMigration.excludeFiles);
593 strings_v sub(subtract(std::move(*vrInclude), std::move(*vrExclude)));
594 vrResult->insert(vrResult->end(), sub.begin(), sub.end());
595 }
596 return vrResult;
597}
598
599namespace
600{
601
602struct componentParts {
603 std::set< OUString > includedPaths;
604 std::set< OUString > excludedPaths;
605};
606
607typedef std::map< OUString, componentParts > Components;
608
609bool getComponent(OUString const & path, OUString * component)
610{
611 OSL_ASSERT(component != nullptr);
612 if (path.isEmpty() || path[0] != '/') {
613 SAL_INFO( "desktop.migration", "configuration migration in/exclude path " << path << " ignored (does not start with slash)" );
614 return false;
615 }
616 sal_Int32 i = path.indexOf('/', 1);
617 *component = i < 0 ? path.copy(1) : path.copy(1, i - 1);
618 return true;
619}
620
621void renameMigratedSetElementTo(
622 css::uno::Reference<css::container::XNameContainer> const & set, OUString const & currentName,
623 OUString const & migratedName)
624{
625 // To avoid unexpected data loss, the code is careful to only rename from currentName to
626 // migratedName in the expected case where the currentName element exists and the migratedName
627 // element doesn't exist:
628 bool const hasCurrent = set->hasByName(currentName);
629 bool const hasMigrated = set->hasByName(migratedName);
630 if (hasCurrent && !hasMigrated) {
631 auto const elem = set->getByName(currentName);
632 set->removeByName(currentName);
633 set->insertByName(migratedName, elem);
634 } else {
635 SAL_INFO_IF(!hasCurrent, "desktop.migration", "unexpectedly missing " << currentName);
636 SAL_INFO_IF(hasMigrated, "desktop.migration", "unexpectedly present " << migratedName);
637 }
638}
639
640void renameMigratedSetElementBack(
641 css::uno::Reference<css::container::XNameContainer> const & set, OUString const & currentName,
642 OUString const & migratedName)
643{
644 // To avoid unexpected data loss, the code is careful to ensure that in the end a currentName
645 // element exists, creating it from a template if the migratedName element had unexpectedly gone
646 // missing:
647 bool const hasMigrated = set->hasByName(migratedName);
648 css::uno::Any elem;
649 if (hasMigrated) {
650 elem = set->getByName(migratedName);
651 set->removeByName(migratedName);
652 } else {
653 SAL_INFO("desktop.migration", "unexpected loss of " << migratedName);
654 elem <<= css::uno::Reference<css::lang::XSingleServiceFactory>(
655 set, css::uno::UNO_QUERY_THROW)->createInstance();
656 }
657 if (set->hasByName(currentName)) {
658 SAL_INFO("desktop.migration", "unexpected reappearance of " << currentName);
659 if (hasMigrated) {
660 SAL_INFO(
661 "desktop.migration",
662 "reappeared " << currentName << " overwritten with " << migratedName);
663 set->replaceByName(currentName, elem);
664 }
665 } else {
666 set->insertByName(currentName, elem);
667 }
668}
669
670}
671
673{
674 Components comps;
675 for (auto const& rMigrationStep : *m_vrMigrations) {
676 for (const OUString& rIncludePath : rMigrationStep.includeConfig) {
677 OUString comp;
678 if (getComponent(rIncludePath, &comp)) {
679 comps[comp].includedPaths.insert(rIncludePath);
680 }
681 }
682 for (const OUString& rExcludePath : rMigrationStep.excludeConfig) {
683 OUString comp;
684 if (getComponent(rExcludePath, &comp)) {
685 comps[comp].excludedPaths.insert(rExcludePath);
686 }
687 }
688 }
689
690 // check if the shared registrymodifications.xcu file exists
691 bool bRegistryModificationsXcuExists = false;
692 OUString regFilePath = m_aInfo.userdata + "/user/registrymodifications.xcu";
693 File regFile(regFilePath);
694 ::osl::FileBase::RC nError = regFile.open(osl_File_OpenFlag_Read);
695 if ( nError == ::osl::FileBase::E_None ) {
696 bRegistryModificationsXcuExists = true;
697 regFile.close();
698 }
699
700 // If the to-be-migrated data contains modifications of
701 // /org.openoffice.Office.UI/ColorScheme/ColorSchemes set elements named after the migrated
702 // product name, those modifications must instead be made to the corresponding set elements
703 // named after the current product name. However, if the current configuration data does not
704 // contain those old-named set elements at all, their modification data would silently be
705 // ignored by css.configuration.XUpdate::insertModificationXcuFile. So temporarily rename any
706 // new-named set elements to their old-named counterparts here, and rename them back again down
707 // below after importing the migrated data:
708 OUString sProductName = utl::ConfigManager::getProductName();
709 OUString sProductNameDark = sProductName + " Dark";
710 OUString sMigratedProductName = m_aInfo.productname;
711 // remove version number from the end of product name if there’s one
712 if (isdigit(sMigratedProductName[sMigratedProductName.getLength() - 1]))
713 sMigratedProductName = (sMigratedProductName.copy(0, m_aInfo.productname.getLength() - 1)).trim();
714 OUString sMigratedProductNameDark = sMigratedProductName + " Dark";
715 auto const tempRename = sMigratedProductName != sProductName;
716 if (tempRename) {
717 auto const batch = comphelper::ConfigurationChanges::create();
718 auto const schemes = officecfg::Office::UI::ColorScheme::ColorSchemes::get(batch);
719 renameMigratedSetElementTo(schemes, sProductName, sMigratedProductName);
720 renameMigratedSetElementTo(schemes, sProductNameDark, sMigratedProductNameDark);
721 batch->commit();
722 }
723
724 for (auto const& comp : comps)
725 {
726 if (!comp.second.includedPaths.empty()) {
727 if (!bRegistryModificationsXcuExists) {
728 // shared registrymodifications.xcu does not exists
729 // the configuration is split in many registry files
730 // determine the file names from the first element in included paths
731 OUStringBuffer buf(m_aInfo.userdata
732 + "/user/registry/data");
733 sal_Int32 n = 0;
734 do {
735 OUString seg(comp.first.getToken(0, '.', n));
736 OUString enc(
737 rtl::Uri::encode(
738 seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict,
739 RTL_TEXTENCODING_UTF8));
740 if (enc.isEmpty() && !seg.isEmpty()) {
741 SAL_INFO( "desktop.migration", "configuration migration component " << comp.first << " ignored (cannot be encoded as file path)" );
742 goto next;
743 }
744 buf.append("/" + enc);
745 } while (n >= 0);
746 buf.append(".xcu");
747 regFilePath = buf.makeStringAndClear();
748 }
749 configuration::Update::get(
751 insertModificationXcuFile(
752 regFilePath,
753 comphelper::containerToSequence(comp.second.includedPaths),
754 comphelper::containerToSequence(comp.second.excludedPaths));
755
756 } else {
757 SAL_INFO( "desktop.migration", "configuration migration component " << comp.first << " ignored (only excludes, no includes)" );
758 }
759next:
760 ;
761 }
762 if (tempRename) {
763 auto const batch = comphelper::ConfigurationChanges::create();
764 auto const schemes = officecfg::Office::UI::ColorScheme::ColorSchemes::get(batch);
765 renameMigratedSetElementBack(schemes, sProductName, sMigratedProductName);
766 renameMigratedSetElementBack(schemes, sProductNameDark, sMigratedProductNameDark);
767 batch->commit();
768 }
769 // checking the migrated (product name related) color scheme name, and replace it to the current version scheme name
770 try
771 {
772 OUString sMigratedColorScheme;
773 uno::Reference<XPropertySet> aPropertySet(
774 getConfigAccess("org.openoffice.Office.UI/ColorScheme", true), uno::UNO_QUERY_THROW);
775 if (aPropertySet->getPropertyValue("CurrentColorScheme") >>= sMigratedColorScheme)
776 {
777 if (sMigratedColorScheme.equals(sMigratedProductName))
778 {
779 aPropertySet->setPropertyValue("CurrentColorScheme",
780 uno::Any(sProductName));
781 uno::Reference<XChangesBatch>(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
782 }
783 else if (sMigratedColorScheme.equals(sMigratedProductNameDark))
784 {
785 aPropertySet->setPropertyValue("CurrentColorScheme",
786 uno::Any(sProductNameDark));
787 uno::Reference<XChangesBatch>(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
788 }
789 }
790 } catch (const Exception&) {
791 // fail silently...
792 }
793}
794
796{
798 try {
799 OUString sAccessSrvc;
800 if (bUpdate)
801 sAccessSrvc = "com.sun.star.configuration.ConfigurationUpdateAccess";
802 else
803 sAccessSrvc = "com.sun.star.configuration.ConfigurationAccess";
804
805 OUString sConfigURL = OUString::createFromAscii(pPath);
806
808 configuration::theDefaultProvider::get(
810
811 // access the provider
812 uno::Sequence< uno::Any > theArgs {uno::Any(sConfigURL)};
813 xNameAccess.set(
814 theConfigProvider->createInstanceWithArguments(
815 sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
816 } catch (const css::uno::Exception&) {
817 TOOLS_WARN_EXCEPTION("desktop.migration", "ignoring");
818 }
819 return xNameAccess;
820}
821
823{
824 OUString localName;
825 OUString destName;
826 OUString userInstall;
828 aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
829 if (aStatus == utl::Bootstrap::PATH_EXISTS) {
830 for (auto const& rFile : *m_vrFileList)
831 {
832 // remove installation prefix from file
833 localName = rFile.copy(m_aInfo.userdata.getLength());
834 if (localName.endsWith( "/autocorr/acor_.dat")) {
835 // Previous versions used an empty language tag for
836 // LANGUAGE_DONTKNOW with the "[All]" autocorrection entry.
837 // As of LibreOffice 4.0 it is 'und' for LANGUAGE_UNDETERMINED
838 // so the file name is "acor_und.dat".
839 localName = OUString::Concat(localName.subView( 0, localName.getLength() - 4)) + "und.dat";
840 }
841 destName = userInstall + localName;
842 INetURLObject aURL(destName);
843 // check whether destination directory exists
844 aURL.removeSegment();
846 FileBase::RC copyResult = File::copy(rFile, destName);
847 if (copyResult != FileBase::E_None) {
848 SAL_WARN( "desktop", "Cannot copy " << rFile << " to " << destName);
849 }
850 }
851 } else {
852 OSL_FAIL("copyFiles: UserInstall does not exist");
853 }
854}
855
857{
858 // Build argument array
859 uno::Sequence< uno::Any > seqArguments(3);
860 auto pseqArguments = seqArguments.getArray();
861 pseqArguments[0] <<= NamedValue("Productname",
863 pseqArguments[1] <<= NamedValue("UserData",
865
866
867 // create an instance of every migration service
868 // and execute the migration job
869 uno::Reference< XJob > xMigrationJob;
870
872 for (auto const& rMigration : *m_vrMigrations)
873 {
874 if( !rMigration.service.isEmpty()) {
875
876 try {
877 // set black list for extension migration
878 uno::Sequence< OUString > seqExtDenyList;
879 sal_uInt32 nSize = rMigration.excludeExtensions.size();
880 if ( nSize > 0 )
881 seqExtDenyList = comphelper::arrayToSequence< OUString >(
882 rMigration.excludeExtensions.data(), nSize );
883 pseqArguments[2] <<= NamedValue("ExtensionDenyList",
884 uno::Any( seqExtDenyList ));
885
886 xMigrationJob.set(
887 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(rMigration.service, seqArguments, xContext),
888 uno::UNO_QUERY_THROW);
889
890 xMigrationJob->execute(uno::Sequence< NamedValue >());
891
892
893 } catch (const Exception&) {
894 TOOLS_WARN_EXCEPTION( "desktop", "Execution of migration service failed. Service: "
895 << rMigration.service);
896 } catch (...) {
897 SAL_WARN( "desktop", "Execution of migration service failed (Exception caught).\nService: "
898 << rMigration.service << "\nNo message available");
899 }
900
901 }
902 }
903}
904
905std::vector< MigrationModuleInfo > MigrationImpl::detectUIChangesForAllModules() const
906{
907 std::vector< MigrationModuleInfo > vModulesInfo;
908 static constexpr OUStringLiteral MENUBAR(u"menubar");
909 static constexpr OUStringLiteral TOOLBAR(u"toolbar");
910
911 uno::Sequence< uno::Any > lArgs {uno::Any(m_aInfo.userdata + "/user/config/soffice.cfg/modules"),
912 uno::Any(embed::ElementModes::READ)};
913
917
918 xModules.set(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
919 if (!xModules.is())
920 return vModulesInfo;
921
922 uno::Sequence< OUString > lNames = xModules->getElementNames();
923 sal_Int32 nLength = lNames.getLength();
924 for (sal_Int32 i=0; i<nLength; ++i) {
925 OUString sModuleShortName = lNames[i];
926 uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ);
927 if (xModule.is()) {
928 MigrationModuleInfo aModuleInfo;
929
930 uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ);
931 if (xMenubar.is()) {
932 if (xMenubar->getElementNames().hasElements()) {
933 aModuleInfo.sModuleShortName = sModuleShortName;
934 aModuleInfo.bHasMenubar = true;
935 }
936 }
937
938 uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ);
939 if (xToolbar.is()) {
940 const ::uno::Sequence< OUString > lToolbars = xToolbar->getElementNames();
941 for (OUString const & sToolbarName : lToolbars) {
942 if (sToolbarName.startsWith("custom_"))
943 continue;
944
945 aModuleInfo.sModuleShortName = sModuleShortName;
946 sal_Int32 nIndex = sToolbarName.lastIndexOf('.');
947 if (nIndex > 0) {
948 std::u16string_view sExtension(sToolbarName.subView(nIndex));
949 OUString sToolbarResourceName(sToolbarName.copy(0, nIndex));
950 if (!sToolbarResourceName.isEmpty() && sExtension == u".xml")
951 aModuleInfo.m_vToolbars.push_back(sToolbarResourceName);
952 }
953 }
954 }
955
956 if (!aModuleInfo.sModuleShortName.isEmpty())
957 vModulesInfo.push_back(aModuleInfo);
958 }
959 }
960
961 return vModulesInfo;
962}
963
964void MigrationImpl::compareOldAndNewConfig(const OUString& sParent,
967 const OUString& sResourceURL)
968{
969 static constexpr OUStringLiteral MENU_SEPARATOR(u" | ");
970
971 std::vector< MigrationItem > vOldItems;
972 std::vector< MigrationItem > vNewItems;
974 sal_Int32 nOldCount = xIndexOld->getCount();
975 sal_Int32 nNewCount = xIndexNew->getCount();
976
977 for (int n=0; n<nOldCount; ++n) {
978 MigrationItem aMigrationItem;
979 if (xIndexOld->getByIndex(n) >>= aProps) {
980 for(beans::PropertyValue const & prop : std::as_const(aProps)) {
981 if ( prop.Name == ITEM_DESCRIPTOR_COMMANDURL )
982 prop.Value >>= aMigrationItem.m_sCommandURL;
983 else if ( prop.Name == ITEM_DESCRIPTOR_CONTAINER )
984 prop.Value >>= aMigrationItem.m_xPopupMenu;
985 }
986
987 if (!aMigrationItem.m_sCommandURL.isEmpty())
988 vOldItems.push_back(aMigrationItem);
989 }
990 }
991
992 for (int n=0; n<nNewCount; ++n) {
993 MigrationItem aMigrationItem;
994 if (xIndexNew->getByIndex(n) >>= aProps) {
995 for(beans::PropertyValue const & prop : std::as_const(aProps)) {
996 if ( prop.Name == ITEM_DESCRIPTOR_COMMANDURL )
997 prop.Value >>= aMigrationItem.m_sCommandURL;
998 else if ( prop.Name == ITEM_DESCRIPTOR_CONTAINER )
999 prop.Value >>= aMigrationItem.m_xPopupMenu;
1000 }
1001
1002 if (!aMigrationItem.m_sCommandURL.isEmpty())
1003 vNewItems.push_back(aMigrationItem);
1004 }
1005 }
1006
1007 OUString sSibling;
1008 for (auto const& oldItem : vOldItems)
1009 {
1010 std::vector< MigrationItem >::iterator pFound = std::find(vNewItems.begin(), vNewItems.end(), oldItem);
1011 if (pFound != vNewItems.end() && oldItem.m_xPopupMenu.is()) {
1012 OUString sName;
1013 if (!sParent.isEmpty())
1014 sName = sParent + MENU_SEPARATOR + oldItem.m_sCommandURL;
1015 else
1016 sName = oldItem.m_sCommandURL;
1017 compareOldAndNewConfig(sName, oldItem.m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL);
1018 } else if (pFound == vNewItems.end()) {
1019 MigrationItem aMigrationItem(sParent, sSibling, oldItem.m_sCommandURL, oldItem.m_xPopupMenu);
1020 if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end()) {
1021 std::vector< MigrationItem > vMigrationItems;
1022 m_aOldVersionItemsHashMap.emplace(sResourceURL, vMigrationItems);
1023 m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1024 } else {
1025 if (std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end())
1026 m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1027 }
1028 }
1029
1030 sSibling = oldItem.m_sCommandURL;
1031 }
1032}
1033
1035 const uno::Reference< container::XIndexContainer>& xIndexContainer,
1036 const OUString& sModuleIdentifier,
1037 const OUString& sResourceURL)
1038{
1039 MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL);
1040 if (pFound==m_aOldVersionItemsHashMap.end())
1041 return;
1042
1043 for (auto const& elem : pFound->second)
1044 {
1045 uno::Reference< container::XIndexContainer > xTemp = xIndexContainer;
1046
1047 OUString sParentNodeName = elem.m_sParentNodeName;
1048 sal_Int32 nIndex = 0;
1049 do {
1050 std::u16string_view sToken( o3tl::trim(o3tl::getToken(sParentNodeName, 0, '|', nIndex)) );
1051 if (sToken.empty())
1052 break;
1053
1054 sal_Int32 nCount = xTemp->getCount();
1055 for (sal_Int32 i=0; i<nCount; ++i) {
1056 OUString sCommandURL;
1057 OUString sLabel;
1059
1061 xTemp->getByIndex(i) >>= aPropSeq;
1062 for (beans::PropertyValue const & prop : std::as_const(aPropSeq)) {
1063 OUString sPropName = prop.Name;
1064 if ( sPropName == ITEM_DESCRIPTOR_COMMANDURL )
1065 prop.Value >>= sCommandURL;
1066 else if ( sPropName == ITEM_DESCRIPTOR_LABEL )
1067 prop.Value >>= sLabel;
1068 else if ( sPropName == ITEM_DESCRIPTOR_CONTAINER )
1069 prop.Value >>= xChild;
1070 }
1071
1072 if (sCommandURL == sToken) {
1073 xTemp = xChild;
1074 break;
1075 }
1076 }
1077
1078 } while (nIndex >= 0);
1079
1080 if (nIndex == -1) {
1081 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(elem.m_sCommandURL, sModuleIdentifier);
1083 beans::PropertyValue(ITEM_DESCRIPTOR_COMMANDURL, 0, uno::Any(elem.m_sCommandURL), beans::PropertyState_DIRECT_VALUE),
1084 beans::PropertyValue(ITEM_DESCRIPTOR_LABEL, 0, uno::Any(vcl::CommandInfoProvider::GetLabelForCommand(aProperties)), beans::PropertyState_DIRECT_VALUE),
1085 beans::PropertyValue(ITEM_DESCRIPTOR_CONTAINER, 0, uno::Any(elem.m_xPopupMenu), beans::PropertyState_DIRECT_VALUE)
1086 };
1087
1088 if (elem.m_sPrevSibling.isEmpty())
1089 xTemp->insertByIndex(0, uno::Any(aPropSeq));
1090 else {
1091 sal_Int32 nCount = xTemp->getCount();
1092 sal_Int32 i = 0;
1093 for (; i<nCount; ++i) {
1094 OUString sCmd;
1096 xTemp->getByIndex(i) >>= aTempPropSeq;
1097 for (beans::PropertyValue const & prop : std::as_const(aTempPropSeq)) {
1098 if ( prop.Name == ITEM_DESCRIPTOR_COMMANDURL ) {
1099 prop.Value >>= sCmd;
1100 break;
1101 }
1102 }
1103
1104 if (sCmd == elem.m_sPrevSibling)
1105 break;
1106 }
1107
1108 xTemp->insertByIndex(i+1, uno::Any(aPropSeq));
1109 }
1110 }
1111 }
1112
1113 if (xIndexContainer.is())
1114 xCfgManager->replaceSettings(sResourceURL, xIndexContainer);
1115
1116 uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY);
1117 if (xUIConfigurationPersistence.is())
1118 xUIConfigurationPersistence->store();
1119}
1120
1122{
1124
1125 for ( const css::beans::PropertyValue& rProp : m_lCfgManagerSeq) {
1126 if (rProp.Name == sModuleShortName) {
1127 rProp.Value >>= xCfgManager;
1128 break;
1129 }
1130 }
1131
1132 return xCfgManager;
1133}
1134
1136{
1138
1139 for (auto const & prop : m_lNewVersionMenubarSettingsSeq) {
1140 if (prop.Name == sModuleShortName) {
1141 prop.Value >>= xNewMenuSettings;
1142 break;
1143 }
1144 }
1145
1146 return xNewMenuSettings;
1147}
1148
1149uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(std::u16string_view sModuleShortName, std::u16string_view sToolbarName) const
1150{
1152
1153 for (auto const & newProp : m_lNewVersionToolbarSettingsSeq) {
1154 if (newProp.Name == sModuleShortName) {
1155 uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq;
1156 newProp.Value >>= lToolbarSettingsSeq;
1157 for (auto const & prop : std::as_const(lToolbarSettingsSeq)) {
1158 if (prop.Name == sToolbarName) {
1159 prop.Value >>= xNewToolbarSettings;
1160 break;
1161 }
1162 }
1163
1164 break;
1165 }
1166 }
1167
1168 return xNewToolbarSettings;
1169}
1170
1171void NewVersionUIInfo::init(const std::vector< MigrationModuleInfo >& vModulesInfo)
1172{
1173 m_lCfgManagerSeq.resize(vModulesInfo.size());
1174 m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size());
1175 auto p_lNewVersionMenubarSettingsSeq = m_lNewVersionMenubarSettingsSeq.getArray();
1176 m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size());
1177 auto p_lNewVersionToolbarSettingsSeq = m_lNewVersionToolbarSettingsSeq.getArray();
1178
1179 static constexpr OUStringLiteral sMenubarResourceURL(u"private:resource/menubar/menubar");
1180 static constexpr OUStringLiteral sToolbarResourcePre(u"private:resource/toolbar/");
1181
1182 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = ui::theModuleUIConfigurationManagerSupplier::get( ::comphelper::getProcessComponentContext() );
1183
1184 for (size_t i=0; i<vModulesInfo.size(); ++i) {
1185 OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
1186 if (!sModuleIdentifier.isEmpty()) {
1187 uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier);
1188 m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName;
1189 m_lCfgManagerSeq[i].Value <<= xCfgManager;
1190
1191 if (vModulesInfo[i].bHasMenubar) {
1192 p_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1193 p_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, true);
1194 }
1195
1196 sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
1197 if (nToolbars > 0) {
1198 uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars);
1199 auto plPropSeq = lPropSeq.getArray();
1200 for (sal_Int32 j=0; j<nToolbars; ++j) {
1201 OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
1202 OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
1203
1204 plPropSeq[j].Name = sToolbarName;
1205 plPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, true);
1206 }
1207
1208 p_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1209 p_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq;
1210 }
1211 }
1212 }
1213}
1214
1215} // namespace desktop
1216
1217/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool removeSegment(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true)
static std::shared_ptr< ConfigurationChanges > create()
static css::uno::Reference< css::container::XNameAccess > getConfigAccess(const char *path, bool rw=false)
Definition: migration.cxx:795
strings_vr getAllFiles(const OUString &baseURL) const
Definition: migration.cxx:531
static void setInstallInfoIfExist(install_info &aInfo, std::u16string_view rConfigDir, const OUString &rVersion)
Definition: migration.cxx:432
migrations_available m_vMigrationsAvailable
static bool checkMigrationCompleted()
Definition: migration.cxx:273
void mergeOldToNewVersion(const css::uno::Reference< css::ui::XUIConfigurationManager > &xCfgManager, const css::uno::Reference< css::container::XIndexContainer > &xIndexContainer, const OUString &sModuleIdentifier, const OUString &sResourceURL)
Definition: migration.cxx:1034
static migrations_vr readMigrationSteps(const OUString &rMigrationName)
Definition: migration.cxx:330
migrations_vr m_vrMigrations
MigrationHashMap m_aOldVersionItemsHashMap
static install_info findInstallation(const strings_v &rVersions)
Definition: migration.cxx:449
void compareOldAndNewConfig(const OUString &sParentNodeName, const css::uno::Reference< css::container::XIndexContainer > &xOldIndexContainer, const css::uno::Reference< css::container::XIndexContainer > &xNewIndexContainer, const OUString &sToolbarName)
Definition: migration.cxx:964
static void readAvailableMigrations(migrations_available &)
Definition: migration.cxx:304
sal_Int32 findPreferredMigrationProcess(const migrations_available &)
Definition: migration.cxx:487
static OUString preXDGConfigDir(const OUString &rConfigDir)
Definition: migration.cxx:402
std::vector< MigrationModuleInfo > detectUIChangesForAllModules() const
Definition: migration.cxx:905
static strings_vr applyPatterns(const strings_v &vSet, const strings_v &vPatterns)
Definition: migration.cxx:509
strings_vr compileFileList()
Definition: migration.cxx:580
static void setMigrationCompleted()
Definition: migration.cxx:262
static void migrateSettingsIfNecessary()
Definition: migration.cxx:155
get the information before copying the ui configuration files of old version to new version
css::uno::Reference< css::container::XIndexContainer > getNewToolbarSettings(std::u16string_view sModuleShortName, std::u16string_view sToolbarName) const
Definition: migration.cxx:1149
void init(const std::vector< MigrationModuleInfo > &vModulesInfo)
Definition: migration.cxx:1171
css::uno::Reference< css::container::XIndexContainer > getNewMenubarSettings(std::u16string_view sModuleShortName) const
Definition: migration.cxx:1135
std::vector< css::beans::PropertyValue > m_lCfgManagerSeq
css::uno::Reference< css::ui::XUIConfigurationManager > getConfigManager(std::u16string_view sModuleShortName) const
Definition: migration.cxx:1121
css::uno::Sequence< css::beans::PropertyValue > m_lNewVersionMenubarSettingsSeq
css::uno::Sequence< css::beans::PropertyValue > m_lNewVersionToolbarSettingsSeq
static PathStatus locateUserInstallation(OUString &_rURL)
static OUString getProductName()
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
URL aURL
float u
OUString sName
const char * name
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2642
sal_Int32 nIndex
sal_Int64 n
uno_Any a
#define LANGUAGE_DONTKNOW
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
aStr
std::set< OUString > includedPaths
Definition: migration.cxx:603
std::set< OUString > excludedPaths
Definition: migration.cxx:604
void set(css::uno::UnoInterfaceReference const &value)
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
Definition: app.cxx:167
std::vector< migration_step > migrations_v
std::vector< supported_migration > migrations_available
static void insertSorted(migrations_available &rAvailableMigrations, supported_migration const &aSupportedMigration)
Definition: migration.cxx:294
std::unique_ptr< migrations_v > migrations_vr
const char XDG_CONFIG_PART[]
Definition: migration.cxx:400
std::unique_ptr< strings_v > strings_vr
std::vector< OUString > strings_v
static FileBase::RC _checkAndCreateDirectory(INetURLObject const &dirURL)
Definition: migration.cxx:386
constexpr OUStringLiteral ITEM_DESCRIPTOR_COMMANDURL
Definition: migration.cxx:73
constexpr OUStringLiteral ITEM_DESCRIPTOR_LABEL
Definition: migration.cxx:75
constexpr OUStringLiteral ITEM_DESCRIPTOR_CONTAINER
Definition: migration.cxx:74
static OUString mapModuleShortNameToIdentifier(std::u16string_view sShortName)
Definition: migration.cxx:77
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
int i
FileStatus
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
enumrange< T >::Iterator begin(enumrange< T >)
end
comp
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
OUString GetLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
constexpr OUStringLiteral sAccessSrvc
define the item, e.g.
css::uno::Reference< css::container::XIndexContainer > m_xPopupMenu
information for the UI elements to be migrated for one module
std::vector< OUString > m_vToolbars
Any result
std::vector< uno::Reference< sheet::XSpreadsheetDocument > > Components
sal_Int32 nLength