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