LibreOffice Module cui (master)  1
optaboutconfig.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 
10 #include "optaboutconfig.hxx"
11 
12 #include <vcl/button.hxx>
13 #include <vcl/event.hxx>
14 #include <vcl/svlbitm.hxx>
15 #include <vcl/treelistentry.hxx>
16 #include <vcl/fixed.hxx>
18 #include <comphelper/sequence.hxx>
19 #include <com/sun/star/configuration/theDefaultProvider.hpp>
20 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
21 #include <com/sun/star/beans/NamedValue.hpp>
22 #include <com/sun/star/beans/Property.hpp>
23 #include <com/sun/star/beans/XProperty.hpp>
24 #include <com/sun/star/container/XNameAccess.hpp>
25 #include <com/sun/star/container/XNameReplace.hpp>
26 #include <com/sun/star/container/XHierarchicalName.hpp>
27 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
28 #include <com/sun/star/util/XChangesBatch.hpp>
29 #include <com/sun/star/util/SearchFlags.hpp>
30 #include <com/sun/star/util/SearchAlgorithms2.hpp>
31 #include <unotools/textsearch.hxx>
32 #include <sal/log.hxx>
33 #include <tools/diagnose_ex.h>
34 
35 #include <memory>
36 #include <vector>
37 #include <iostream>
38 
39 using namespace ::com::sun::star;
40 using namespace com::sun::star::uno;
41 using namespace com::sun::star::container;
42 
43 #define SHORT_LEN_LIMIT 7
44 #define LONG_LEN_LIMIT 11
45 #define HYPER_LEN_LIMIT 20
46 
47 struct Prop_Impl
48 {
49  OUString Name;
50  OUString Property;
52 
53  Prop_Impl( const OUString& sName, const OUString& sProperty, const Any& aValue )
54  : Name( sName )
55  , Property( sProperty )
56  , Value( aValue )
57  {}
58 };
59 
60 struct UserData
61 {
62  bool bIsPropertyPath;
63  OUString sPropertyPath;
64  int aLineage;
65  Reference<XNameAccess> aXNameAccess;
66 
67  explicit UserData( OUString const & rPropertyPath )
68  : bIsPropertyPath( true )
69  , sPropertyPath(rPropertyPath)
70  , aLineage(0)
71  {}
72 
73  explicit UserData( Reference<XNameAccess> const & rXNameAccess, int rIndex )
74  : bIsPropertyPath( false )
75  , aLineage(rIndex)
76  , aXNameAccess( rXNameAccess )
77  {}
78 };
79 
80 IMPL_LINK(CuiAboutConfigValueDialog, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
81 {
82  bool bValid = false;
83  bool bNonSpace = rKeyEvent.GetKeyCode().GetCode() != KEY_SPACE;
84  if (m_bNumericOnly && bNonSpace )
85  {
86  const vcl::KeyCode& rKeyCode = rKeyEvent.GetKeyCode();
87  sal_uInt16 nGroup = rKeyCode.GetGroup();
88  sal_uInt16 nKey = rKeyCode.GetCode();
89 
90  switch ( nGroup ) {
91  case KEYGROUP_NUM :
92  case KEYGROUP_CURSOR :
93  {
94  bValid = true;
95  break;
96  }
97 
98  case KEYGROUP_MISC :
99  {
100  switch ( nKey ) {
101  case KEY_SUBTRACT :
102  case KEY_COMMA :
103  case KEY_POINT :
104  {
105  bValid = true;
106  break;
107  }
108 
109  default :
110  {
111  if( nKey < KEY_ADD || nKey > KEY_EQUAL )
112  bValid = true;
113  break;
114  }
115  }
116  break;
117  }
118 
119  default :
120  {
121  bValid = false;
122  break;
123  }
124  }
125 
126  //Select all, Copy, Paste, Cut, Undo Keys
127  if ( !bValid && ( rKeyCode.IsMod1() && (
128  KEY_A == nKey || KEY_C == nKey || KEY_V == nKey || KEY_X == nKey || KEY_Z == nKey ) ) )
129  bValid = true;
130  }
131  else
132  bValid = true;
133 
134  //if value return true to claim that it has been handled
135  return !bValid;
136 }
137 
138 CuiAboutConfigTabPage::CuiAboutConfigTabPage( vcl::Window* pParent/*, const SfxItemSet& rItemSet*/ ) :
139  ModalDialog( pParent, "AboutConfig", "cui/ui/aboutconfigdialog.ui"),
140  m_pPrefCtrl( get<SvSimpleTableContainer>("preferences") ),
141  m_pResetBtn( get<PushButton>("reset") ),
142  m_pEditBtn( get<PushButton>("edit") ),
143  m_pSearchBtn( get<PushButton>("searchButton") ),
144  m_pSearchEdit( get<Edit>("searchEntry") ),
145  m_vectorOfModified(),
146  m_pPrefBox( VclPtr<SvSimpleTable>::Create(*m_pPrefCtrl, WB_SCROLL | WB_HSCROLL | WB_VSCROLL ) )
147 {
148  Size aControlSize(LogicToPixel(Size(385, 230), MapMode(MapUnit::MapAppFont)));
149  m_pPrefCtrl->set_width_request(aControlSize.Width());
150  m_pPrefCtrl->set_height_request(aControlSize.Height());
151 
152  m_pEditBtn->SetClickHdl( LINK( this, CuiAboutConfigTabPage, StandardHdl_Impl ) );
153  m_pResetBtn->SetClickHdl( LINK( this, CuiAboutConfigTabPage, ResetBtnHdl_Impl ) );
154  m_pPrefBox->SetDoubleClickHdl( LINK(this, CuiAboutConfigTabPage, DoubleClickHdl_Impl) );
155  m_pPrefBox->SetExpandingHdl( LINK(this, CuiAboutConfigTabPage, ExpandingHdl_Impl) );
156  m_pSearchBtn->SetClickHdl( LINK(this, CuiAboutConfigTabPage, SearchHdl_Impl) );
157 
158  m_pPrefBox->InsertHeaderEntry(get<FixedText>("preference")->GetText());
159  m_pPrefBox->InsertHeaderEntry(get<FixedText>("property")->GetText());
160  m_pPrefBox->InsertHeaderEntry(get<FixedText>("type")->GetText());
161  m_pPrefBox->InsertHeaderEntry(get<FixedText>("value")->GetText());
162 
163  float fWidth = approximate_char_width();
164 
165  long aTabs[] = {0,0,0,0};
166  aTabs[1] = fWidth * 65;
167  aTabs[2] = aTabs[1] + fWidth * 20;
168  aTabs[3] = aTabs[2] + fWidth * 8;
169 
170  m_options.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
171  m_options.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
172  m_options.searchFlag |= (util::SearchFlags::REG_NOT_BEGINOFLINE |
173  util::SearchFlags::REG_NOT_ENDOFLINE);
174 
175  m_pPrefBox->SetTabs(SAL_N_ELEMENTS(aTabs), aTabs, MapUnit::MapPixel);
176  m_pPrefBox->SetAlternatingRowColors( true );
177 }
178 
180 {
181  disposeOnce();
182 }
183 
185 {
187  m_pPrefCtrl.clear();
188  m_pResetBtn.clear();
189  m_pEditBtn.clear();
193 }
194 
195 void CuiAboutConfigTabPage::InsertEntry(const OUString& rPropertyPath, const OUString& rProp, const OUString& rStatus,
196  const OUString& rType, const OUString& rValue, SvTreeListEntry *pParentEntry,
197  bool bInsertToPrefBox)
198 {
199  SvTreeListEntry* pEntry = new SvTreeListEntry;
200  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(
201  Image(), Image(), false)); //It is needed, otherwise causes crash
202  pEntry->AddItem(std::make_unique<SvLBoxString>(rProp));
203  pEntry->AddItem(std::make_unique<SvLBoxString>(rStatus));
204  pEntry->AddItem(std::make_unique<SvLBoxString>(rType));
205  pEntry->AddItem(std::make_unique<SvLBoxString>(rValue));
206  m_vectorUserData.push_back(std::make_unique<UserData>(rPropertyPath));
207  pEntry->SetUserData(m_vectorUserData.back().get());
208 
209  if(bInsertToPrefBox)
210  m_pPrefBox->Insert( pEntry, pParentEntry );
211  else
212  m_prefBoxEntries.push_back(std::unique_ptr<SvTreeListEntry>(pEntry));
213 }
214 
216 {
217  m_pPrefBox->Clear();
218 
219  m_vectorOfModified.clear();
220  m_pPrefBox->GetModel()->SetSortMode( SortNone );
221  m_prefBoxEntries.clear();
222  m_modifiedPrefBoxEntries.clear();
223 
224  m_pPrefBox->SetUpdateMode(false);
225  Reference< XNameAccess > xConfigAccess = getConfigAccess( "/", false );
226  //Load all XNameAccess to m_prefBoxEntries
227  FillItems( xConfigAccess, nullptr, 0, true );
228  //Load xConfigAccess' children to m_prefBox
229  FillItems( xConfigAccess );
230  m_pPrefBox->SetUpdateMode(true);
231 }
232 
234 {
235  std::vector< std::shared_ptr< Prop_Impl > >::iterator pIter;
236  for( pIter = m_vectorOfModified.begin() ; pIter != m_vectorOfModified.end(); ++pIter )
237  {
238  Reference< XNameAccess > xUpdateAccess = getConfigAccess( (*pIter)->Name , true );
239  Reference< XNameReplace > xNameReplace( xUpdateAccess, UNO_QUERY_THROW );
240 
241  xNameReplace->replaceByName( (*pIter)->Property, (*pIter)->Value );
242 
243  Reference< util::XChangesBatch > xChangesBatch( xUpdateAccess, UNO_QUERY_THROW );
244  xChangesBatch->commitChanges();
245  }
246 }
247 
249  int lineage, bool bLoadAll)
250 {
251  OUString sPath = Reference< XHierarchicalName >(
252  xNameAccess, uno::UNO_QUERY_THROW )->getHierarchicalName();
253  uno::Sequence< OUString > seqItems = xNameAccess->getElementNames();
254  for( sal_Int32 i = 0; i < seqItems.getLength(); ++i )
255  {
256  Any aNode = xNameAccess->getByName( seqItems[i] );
257 
258  bool bNotLeaf = false;
259 
260  Reference< XNameAccess > xNextNameAccess;
261  try
262  {
263  xNextNameAccess.set(aNode, uno::UNO_QUERY);
264  bNotLeaf = xNextNameAccess.is();
265  }
266  catch (const RuntimeException&)
267  {
268  TOOLS_WARN_EXCEPTION( "cui.options", "CuiAboutConfigTabPage");
269  }
270 
271  if (bNotLeaf)
272  {
273  if(bLoadAll)
274  FillItems(xNextNameAccess, nullptr, lineage + 1, true);
275  else
276  {
277  // not leaf node
278  SvTreeListEntry* pEntry = new SvTreeListEntry;
279  pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(
282  pEntry->AddItem(std::make_unique<SvLBoxString>(seqItems[i]));
283  //It is needed, without this the selection line will be truncated.
284  pEntry->AddItem(std::make_unique<SvLBoxString>(""));
285  pEntry->AddItem(std::make_unique<SvLBoxString>(""));
286  pEntry->AddItem(std::make_unique<SvLBoxString>(""));
287 
288  m_vectorUserData.push_back(std::make_unique<UserData>(xNextNameAccess, lineage + 1));
289  pEntry->SetUserData(m_vectorUserData.back().get());
290  pEntry->EnableChildrenOnDemand();
291  m_pPrefBox->Insert( pEntry, pParentEntry );
292  }
293  }
294  else
295  {
296  // leaf node
297  OUString sPropertyName = seqItems[i];
298  SvTreeListEntries::iterator it = std::find_if(m_modifiedPrefBoxEntries.begin(), m_modifiedPrefBoxEntries.end(),
299  [&sPath, &sPropertyName](std::unique_ptr<SvTreeListEntry> const& pEntry) -> bool
300  {
301  return static_cast<UserData*>(pEntry->GetUserData())->sPropertyPath == sPath
302  && static_cast<SvLBoxString&>(pEntry->GetItem(2)).GetText() == sPropertyName;
303  }
304  );
305 
306  OUString sType = aNode.getValueTypeName();
307  OUStringBuffer sValue;
308 
309  if (it != m_modifiedPrefBoxEntries.end())
310  sValue = static_cast< SvLBoxString& >( (*it)->GetItem(4) ).GetText();
311  else
312  {
313  switch( aNode.getValueType().getTypeClass() )
314  {
315  case css::uno::TypeClass_VOID:
316  break;
317 
318  case css::uno::TypeClass_BOOLEAN:
319  sValue = OUString::boolean( aNode.get<bool>() );
320  break;
321 
322  case css::uno::TypeClass_SHORT:
323  case css::uno::TypeClass_LONG:
324  case css::uno::TypeClass_HYPER:
325  sValue = OUString::number( aNode.get<sal_Int64>() );
326  break;
327 
328  case css::uno::TypeClass_DOUBLE:
329  sValue = OUString::number( aNode.get<double>() );
330  break;
331 
332  case css::uno::TypeClass_STRING:
333  sValue = aNode.get<OUString>();
334  break;
335 
336  case css::uno::TypeClass_SEQUENCE:
337  if( sType == "[]boolean" )
338  {
339  uno::Sequence<sal_Bool> seq = aNode.get< uno::Sequence<sal_Bool> >();
340  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
341  {
342  if( j != 0 )
343  {
344  sValue.append(",");
345  }
346  sValue.append(OUString::boolean( seq[j] ));
347  }
348  }
349  else if( sType == "[]byte" )
350  {
351  uno::Sequence<sal_Int8> seq = aNode.get< uno::Sequence<sal_Int8> >();
352  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
353  {
354  OUString s = OUString::number(
355  static_cast<sal_uInt8>(seq[j]), 16 );
356  if( s.getLength() == 1 )
357  {
358  sValue.append("0");
359  }
360  sValue.append(s.toAsciiUpperCase());
361  }
362  }
363  else if( sType == "[][]byte" )
364  {
365  uno::Sequence< uno::Sequence<sal_Int8> > seq = aNode.get< uno::Sequence< uno::Sequence<sal_Int8> > >();
366  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
367  {
368  if( j != 0 )
369  {
370  sValue.append(",");
371  }
372  for( sal_Int32 k = 0; k != seq[j].getLength(); ++k )
373  {
374  OUString s = OUString::number(
375  static_cast<sal_uInt8>(seq[j][k]), 16 );
376  if( s.getLength() == 1 )
377  {
378  sValue.append("0");
379  }
380  sValue.append(s.toAsciiUpperCase());
381  }
382  }
383  }
384  else if( sType == "[]short" )
385  {
386  uno::Sequence<sal_Int16> seq = aNode.get< uno::Sequence<sal_Int16> >();
387  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
388  {
389  if( j != 0 )
390  {
391  sValue.append(",");
392  }
393  sValue.append(OUString::number( seq[j] ));
394  }
395  }
396  else if( sType == "[]long" )
397  {
398  uno::Sequence<sal_Int32> seq = aNode.get< uno::Sequence<sal_Int32> >();
399  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
400  {
401  if( j != 0 )
402  {
403  sValue.append(",");
404  }
405  sValue.append(OUString::number( seq[j] ));
406  }
407  }
408  else if( sType == "[]hyper" )
409  {
410  uno::Sequence<sal_Int64> seq = aNode.get< uno::Sequence<sal_Int64> >();
411  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
412  {
413  if( j != 0 )
414  {
415  sValue.append(",");
416  }
417  sValue.append(OUString::number( seq[j] ));
418  }
419  }
420  else if( sType == "[]double" )
421  {
422  uno::Sequence<double> seq = aNode.get< uno::Sequence<double> >();
423  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
424  {
425  if( j != 0 )
426  {
427  sValue.append(",");
428  }
429  sValue.append(OUString::number( seq[j] ));
430  }
431  }
432  else if( sType == "[]string" )
433  {
434  uno::Sequence<OUString> seq = aNode.get< uno::Sequence<OUString> >();
435  for( sal_Int32 j = 0; j != seq.getLength(); ++j )
436  {
437  if( j != 0 )
438  {
439  sValue.append(",");
440  }
441  sValue.append(seq[j]);
442  }
443  }
444  else
445  {
446  SAL_WARN(
447  "cui.options",
448  "path \"" << sPath << "\" member " << seqItems[i]
449  << " of unsupported type " << sType);
450  }
451  break;
452 
453  default:
454  SAL_WARN(
455  "cui.options",
456  "path \"" << sPath << "\" member " << seqItems[i]
457  << " of unsupported type " << sType);
458  break;
459  }
460  }
461 
462  //Short name
463  int index = 0;
464  for(int j = 1; j < lineage; ++j)
465  index = sPath.indexOf("/", index + 1);
466 
467  InsertEntry(sPath, sPath.copy(index+1), seqItems[i], sType, sValue.makeStringAndClear(), pParentEntry, !bLoadAll);
468  }
469  }
470 }
471 
472 Reference< XNameAccess > CuiAboutConfigTabPage::getConfigAccess( const OUString& sNodePath, bool bUpdate )
473 {
474  uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
475 
476  uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
477  css::configuration::theDefaultProvider::get( xContext ) );
478 
479  beans::NamedValue aProperty;
480  aProperty.Name = "nodepath";
481  aProperty.Value <<= sNodePath;
482 
483  uno::Sequence< uno::Any > aArgumentList( 1 );
484  aArgumentList[0] <<= aProperty;
485 
486  OUString sAccessString;
487 
488  if( bUpdate )
489  sAccessString = "com.sun.star.configuration.ConfigurationUpdateAccess";
490  else
491  sAccessString = "com.sun.star.configuration.ConfigurationAccess";
492 
493  uno::Reference< container::XNameAccess > xNameAccess(
494  xConfigProvider->createInstanceWithArguments(
495  sAccessString, aArgumentList ),
496  uno::UNO_QUERY_THROW );
497 
498  return xNameAccess;
499 }
500 
501 void CuiAboutConfigTabPage::AddToModifiedVector( const std::shared_ptr< Prop_Impl >& rProp )
502 {
503  bool isModifiedBefore = false;
504  //Check if value modified before
505  for(std::shared_ptr<Prop_Impl> & nInd : m_vectorOfModified)
506  {
507  if( rProp->Name == nInd->Name && rProp->Property == nInd->Property )
508  {
509  //property modified before. Assign reference to the modified value
510  //do your changes on this object. They will be saved later.
511  nInd = rProp;
512  isModifiedBefore = true;
513  break;
514  }
515  }
516 
517  if( !isModifiedBefore )
518  m_vectorOfModified.push_back( rProp );
519  //property is not modified before
520 }
521 
522 std::vector< OUString > CuiAboutConfigTabPage::commaStringToSequence( const OUString& rCommaSepString )
523 {
524  std::vector<OUString> tempVector;
525 
526  sal_Int32 index = 0;
527  do
528  {
529  OUString word = rCommaSepString.getToken(0, u',', index);
530  word = word.trim();
531  if( !word.isEmpty())
532  tempVector.push_back(word);
533  }while( index >= 0 );
534  return tempVector;
535 }
536 
538  const OUString& rValue,
539  int limit)
540  : GenericDialogController(pWindow, "cui/ui/aboutconfigvaluedialog.ui", "AboutConfigValueDialog")
541  , m_bNumericOnly(limit != 0)
542  , m_xEDValue(m_xBuilder->weld_entry("valuebox"))
543 {
544  if (limit)
545  m_xEDValue->set_max_length(limit);
546  m_xEDValue->set_text(rValue);
547  m_xEDValue->connect_key_press(LINK(this, CuiAboutConfigValueDialog, KeyInputHdl));
548 }
549 
551 {
552 }
553 
554 IMPL_LINK_NOARG( CuiAboutConfigTabPage, ResetBtnHdl_Impl, Button*, void )
555 {
556  Reset();
557 }
558 
559 IMPL_LINK_NOARG( CuiAboutConfigTabPage, DoubleClickHdl_Impl, SvTreeListBox*, bool )
560 {
561  StandardHdl_Impl(nullptr);
562  return true;
563 }
564 
565 IMPL_LINK_NOARG( CuiAboutConfigTabPage, StandardHdl_Impl, Button*, void )
566 {
567  SvTreeListEntry* pEntry = m_pPrefBox->GetHdlEntry();
568  if(pEntry == nullptr)
569  return;
570 
571  UserData *pUserData = static_cast<UserData*>(pEntry->GetUserData());
572  if(pUserData && pUserData->bIsPropertyPath)
573  {
574  //if selection is a node
575  OUString sPropertyName = SvTabListBox::GetEntryText( pEntry, 1 );
576  OUString sPropertyType = SvTabListBox::GetEntryText( pEntry, 2 );
577  OUString sPropertyValue = SvTabListBox::GetEntryText( pEntry, 3 );
578 
579  std::shared_ptr< Prop_Impl > pProperty (new Prop_Impl( pUserData->sPropertyPath, sPropertyName, Any( sPropertyValue ) ) );
580  bool bSaveChanges = false;
581 
582  bool bOpenDialog = true;
583  OUString sDialogValue;
584  OUString sNewValue;
585 
586  if( sPropertyType == "boolean" )
587  {
588  bool bValue;
589  if( sPropertyValue == "true" )
590  {
591  sDialogValue = "false";
592  bValue = false;
593  }
594  else
595  {
596  sDialogValue = "true";
597  bValue = true;
598  }
599 
600  pProperty->Value <<= bValue;
601  bOpenDialog = false;
602  bSaveChanges = true;
603  }
604  else if ( sPropertyType == "void" )
605  {
606  bOpenDialog = false;
607  }
608  else
609  {
610  sDialogValue = sPropertyValue;
611  bOpenDialog = true;
612  }
613 
614  try
615  {
616  if( bOpenDialog )
617  {
618  //Cosmetic length limit for integer values.
619  int limit=0;
620  if( sPropertyType == "short" )
621  limit = SHORT_LEN_LIMIT;
622  else if( sPropertyType == "long" )
623  limit = LONG_LEN_LIMIT;
624  else if( sPropertyType == "hyper" )
625  limit = HYPER_LEN_LIMIT;
626 
627  CuiAboutConfigValueDialog aValueDialog(GetFrameWeld(), sDialogValue, limit);
628 
629  if (aValueDialog.run() == RET_OK )
630  {
631  sNewValue = aValueDialog.getValue();
632  bSaveChanges = true;
633  if ( sPropertyType == "short")
634  {
635  sal_Int16 nShort;
636  sal_Int32 nNumb = sNewValue.toInt32();
637 
638  //if the value is 0 and length is not 1, there is something wrong
639  if( ( nNumb==0 && sNewValue.getLength()!=1 ) || nNumb > SAL_MAX_INT16 || nNumb < SAL_MIN_INT16)
640  throw uno::Exception("out of range short", nullptr);
641  nShort = static_cast<sal_Int16>(nNumb);
642  pProperty->Value <<= nShort;
643  }
644  else if( sPropertyType == "long" )
645  {
646  sal_Int32 nLong = sNewValue.toInt32();
647  if( nLong==0 && sNewValue.getLength()!=1)
648  throw uno::Exception("out of range long", nullptr);
649  pProperty->Value <<= nLong;
650  }
651  else if( sPropertyType == "hyper")
652  {
653  sal_Int64 nHyper = sNewValue.toInt64();
654  if( nHyper==0 && sNewValue.getLength()!=1)
655  throw uno::Exception("out of range hyper", nullptr);
656  pProperty->Value <<= nHyper;
657  }
658  else if( sPropertyType == "double")
659  {
660  double nDoub = sNewValue.toDouble();
661  if( nDoub ==0 && sNewValue.getLength()!=1)
662  throw uno::Exception("out of range double", nullptr);
663  pProperty->Value <<= nDoub;
664  }
665  else if( sPropertyType == "float")
666  {
667  float nFloat = sNewValue.toFloat();
668  if( nFloat ==0 && sNewValue.getLength()!=1)
669  throw uno::Exception("out of range float", nullptr);
670  pProperty->Value <<= nFloat;
671  }
672  else if( sPropertyType == "string" )
673  {
674  pProperty->Value <<= sNewValue;
675  }
676  else if( sPropertyType == "[]short" )
677  {
678  //create string sequence from comma separated string
679  //uno::Sequence< OUString > seqStr;
680  std::vector< OUString > seqStr = commaStringToSequence( sNewValue );
681 
682  //create appropriate sequence with same size as string sequence
683  uno::Sequence< sal_Int16 > seqShort( seqStr.size() );
684  //convert all strings to appropriate type
685  for( size_t i = 0; i < seqStr.size(); ++i )
686  {
687  seqShort[i] = static_cast<sal_Int16>(seqStr[i].toInt32());
688  }
689  pProperty->Value <<= seqShort;
690  }
691  else if( sPropertyType == "[]long" )
692  {
693  std::vector< OUString > seqStrLong = commaStringToSequence( sNewValue );
694 
695  uno::Sequence< sal_Int32 > seqLong( seqStrLong.size() );
696  for( size_t i = 0; i < seqStrLong.size(); ++i )
697  {
698  seqLong[i] = seqStrLong[i].toInt32();
699  }
700  pProperty->Value <<= seqLong;
701  }
702  else if( sPropertyType == "[]hyper" )
703  {
704  std::vector< OUString > seqStrHyper = commaStringToSequence( sNewValue );
705  uno::Sequence< sal_Int64 > seqHyper( seqStrHyper.size() );
706  for( size_t i = 0; i < seqStrHyper.size(); ++i )
707  {
708  seqHyper[i] = seqStrHyper[i].toInt64();
709  }
710  pProperty->Value <<= seqHyper;
711  }
712  else if( sPropertyType == "[]double" )
713  {
714  std::vector< OUString > seqStrDoub = commaStringToSequence( sNewValue );
715  uno::Sequence< double > seqDoub( seqStrDoub.size() );
716  for( size_t i = 0; i < seqStrDoub.size(); ++i )
717  {
718  seqDoub[i] = seqStrDoub[i].toDouble();
719  }
720  pProperty->Value <<= seqDoub;
721  }
722  else if( sPropertyType == "[]float" )
723  {
724  std::vector< OUString > seqStrFloat = commaStringToSequence( sNewValue );
725  uno::Sequence< sal_Int16 > seqFloat( seqStrFloat.size() );
726  for( size_t i = 0; i < seqStrFloat.size(); ++i )
727  {
728  seqFloat[i] = seqStrFloat[i].toFloat();
729  }
730  pProperty->Value <<= seqFloat;
731  }
732  else if( sPropertyType == "[]string" )
733  {
734  pProperty->Value <<= comphelper::containerToSequence( commaStringToSequence( sNewValue ));
735  }
736  else //unknown
737  throw uno::Exception("unknown property type " + sPropertyType, nullptr);
738 
739  sDialogValue = sNewValue;
740  }
741  }
742 
743  if(bSaveChanges)
744  {
745  AddToModifiedVector( pProperty );
746 
747  //update listbox value.
748  m_pPrefBox->SetEntryText( sDialogValue, pEntry, 3 );
749  //update m_prefBoxEntries
750  SvTreeListEntries::iterator it = std::find_if(m_prefBoxEntries.begin(), m_prefBoxEntries.end(),
751  [&pUserData, &sPropertyName](std::unique_ptr<SvTreeListEntry> const& rpEntry) -> bool
752  {
753  return static_cast<UserData*>(rpEntry->GetUserData())->sPropertyPath == pUserData->sPropertyPath
754  && static_cast<SvLBoxString&>(rpEntry->GetItem(2)).GetText() == sPropertyName;
755  }
756  );
757  if (it != m_prefBoxEntries.end())
758  {
759  (*it)->ReplaceItem(std::make_unique<SvLBoxString>(sDialogValue), 4);
760 
761  SvTreeListEntries::iterator modifiedIt = std::find_if(
762  m_modifiedPrefBoxEntries.begin(), m_modifiedPrefBoxEntries.end(),
763  [&pUserData, &sPropertyName](std::unique_ptr<SvTreeListEntry> const& rpEntry) -> bool
764  {
765  return static_cast<UserData*>(rpEntry->GetUserData())->sPropertyPath == pUserData->sPropertyPath
766  && static_cast<SvLBoxString&>(rpEntry->GetItem(2)).GetText() == sPropertyName;
767  }
768  );
769 
770  if( modifiedIt != m_modifiedPrefBoxEntries.end())
771  {
772  (*modifiedIt)->ReplaceItem(std::make_unique<SvLBoxString>(sDialogValue), 4);
773  }
774  else
775  {
776  std::unique_ptr<SvTreeListEntry> pCloneEntry(
777  new SvTreeListEntry);
778  pCloneEntry->Clone((*it).get());
779  m_modifiedPrefBoxEntries.push_back(std::move(pCloneEntry));
780  }
781  }
782  }
783  }
784  catch( uno::Exception& )
785  {
786  }
787  }
788 }
789 
791 {
792  m_pPrefBox->Clear();
793  m_pPrefBox->SetUpdateMode( false );
794 
795  SvSortMode sortMode = m_pPrefBox->GetModel()->GetSortMode();
796  sal_uInt16 sortedCol = m_pPrefBox->GetSortedCol();
797 
798  if( sortMode != SortNone )
799  m_pPrefBox->SortByCol( 0xFFFF );
800 
801  if( m_pSearchEdit->GetText().isEmpty() )
802  {
803  m_pPrefBox->Clear();
804  Reference< XNameAccess > xConfigAccess = getConfigAccess( "/", false );
805  FillItems( xConfigAccess );
806  }
807  else
808  {
809  m_options.searchString = m_pSearchEdit->GetText();
810  utl::TextSearch textSearch( m_options );
811  for (auto const& it : m_prefBoxEntries)
812  {
813  sal_Int32 endPos, startPos = 0;
814 
815  for(size_t i = 1; i < it->ItemCount(); ++i)
816  {
817  OUString scrTxt;
818  if(i == 1)
819  scrTxt = static_cast< UserData* >( it->GetUserData() )->sPropertyPath;
820  else
821  scrTxt = static_cast< SvLBoxString& >( it->GetItem(i) ).GetText();
822  endPos = scrTxt.getLength();
823  if( textSearch.SearchForward( scrTxt, &startPos, &endPos ) )
824  {
825  SvTreeListEntry* pEntry = new SvTreeListEntry;
826  pEntry->Clone( it.get() );
827  InsertEntry( pEntry );
828  break;
829  }
830  }
831  }
832  }
833 
834  if( sortMode != SortNone )
835  m_pPrefBox->SortByCol(sortedCol, sortMode == SortAscending);
836 
837  m_pPrefBox->SetUpdateMode( true );
838 }
839 
841 {
842  OUString sPathWithProperty = static_cast< UserData* >(pEntry->GetUserData())->sPropertyPath;
843  sal_Int32 index = sPathWithProperty.lastIndexOf(static_cast< SvLBoxString& >(pEntry->GetItem(1)).GetText());
844  OUString sPath = sPathWithProperty.copy(0, index);
845  index = 0;
846  SvTreeListEntry* pParentEntry;
847  SvTreeListEntry* pGrandParentEntry = nullptr;
848 
849  do
850  {
851  int prevIndex = index;
852  index = sPath.indexOf("/", index+1);
853  // deal with no parent case (tdf#107811)
854  if (index < 0)
855  {
856  m_pPrefBox->Insert( pEntry, nullptr);
857  return;
858  }
859  OUString sParentName = sPath.copy(prevIndex+1, index - prevIndex - 1);
860 
861  bool hasEntry = false;
862  for(pParentEntry = m_pPrefBox->FirstChild(pGrandParentEntry); pParentEntry != nullptr; pParentEntry = pParentEntry->NextSibling())
863  if(static_cast< SvLBoxString& >(pParentEntry->GetItem(1)).GetText() == sParentName)
864  {
865  hasEntry = true;
866  break;
867  }
868 
869  if(!hasEntry)
870  {
871  pParentEntry = new SvTreeListEntry;
872  pParentEntry->AddItem(std::make_unique<SvLBoxContextBmp>(
875  pParentEntry->AddItem(std::make_unique<SvLBoxString>(sParentName));
876  //It is needed, without this the selection line will be truncated.
877  pParentEntry->AddItem(std::make_unique<SvLBoxString>(""));
878  pParentEntry->AddItem(std::make_unique<SvLBoxString>(""));
879  pParentEntry->AddItem(std::make_unique<SvLBoxString>(""));
880  pParentEntry->EnableChildrenOnDemand(false);
881  m_pPrefBox->Insert( pParentEntry, pGrandParentEntry );
882  }
883 
884  if(pGrandParentEntry)
885  m_pPrefBox->Expand( pGrandParentEntry );
886  pGrandParentEntry = pParentEntry;
887  } while(index < sPath.getLength() - 1);
888 
889  m_pPrefBox->Insert( pEntry, pParentEntry );
890  m_pPrefBox->Expand( pParentEntry );
891 }
892 
894 {
895  SvTreeListEntry* pEntry = m_pPrefBox->GetHdlEntry();
896 
897  if(pEntry != nullptr && pEntry->HasChildrenOnDemand())
898  {
899  pEntry->EnableChildrenOnDemand(false);
900  SvTreeListEntry *pFirstChild = m_pPrefBox->FirstChild(pEntry);
901  if(pFirstChild)
902  m_pPrefBox->RemoveEntry(pFirstChild);
903 
904  if(pEntry->GetUserData() != nullptr)
905  {
906  UserData *pUserData = static_cast<UserData*>(pEntry->GetUserData());
907  FillItems( pUserData->aXNameAccess, pEntry, pUserData->aLineage );
908  }
909  }
910 
911  return pEntry && pEntry->HasChildren();
912 }
913 
914 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
void AddItem(std::unique_ptr< SvLBoxItem > pItem)
#define KEY_V
#define KEY_SUBTRACT
long Width() const
std::vector< std::unique_ptr< UserData > > m_vectorUserData
float approximate_char_width() const
#define KEYGROUP_CURSOR
void SetUserData(void *pPtr)
#define KEY_SPACE
virtual void SetTabs() override
void SetClickHdl(const Link< Button *, void > &rLink)
long Height() const
#define KEY_C
SortNone
void disposeAndClear()
void InsertEntry(SvTreeListEntry *pEntry)
#define KEYGROUP_NUM
SvTreeListEntries m_prefBoxEntries
sal_uInt16 GetGroup() const
sal_uInt16 GetCode() const
virtual ~CuiAboutConfigValueDialog() override
CuiAboutConfigValueDialog(weld::Window *pWindow, const OUString &rValue, int limit)
WinBits const WB_VSCROLL
#define SHORT_LEN_LIMIT
void AddToModifiedVector(const std::shared_ptr< Prop_Impl > &rProp)
#define LONG_LEN_LIMIT
virtual void dispose() override
WinBits const WB_HSCROLL
weld::Window * GetFrameWeld(SfxFrame *pFrame)
SvTreeListEntry * NextSibling() const
SvTreeListEntries m_modifiedPrefBoxEntries
static const Image & GetDefaultExpandedNodeImage()
SortAscending
#define KEY_A
#define SAL_N_ELEMENTS(arr)
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
i18nutil::SearchOptions2 m_options
void clear()
#define TOOLS_WARN_EXCEPTION(area, stream)
IMPL_LINK_NOARG(CuiAboutConfigTabPage, ResetBtnHdl_Impl, Button *, void)
void Clone(SvTreeListEntry *pSource)
WinBits const WB_SCROLL
VclPtr< Edit > m_pSearchEdit
Prop_Impl(const OUString &sName, const OUString &sProperty, const Any &aValue)
TransliterationFlags transliterateFlags
std::unique_ptr< weld::Entry > m_xEDValue
int i
VclPtr< PushButton > m_pEditBtn
VclPtr< PushButton > m_pSearchBtn
void * GetUserData() const
float u
static const Image & GetDefaultCollapsedNodeImage()
VclPtr< SvSimpleTable > m_pPrefBox
VclPtr< PushButton > m_pResetBtn
#define KEY_COMMA
tuple index
const SvLBoxItem & GetItem(size_t nPos) const
#define KEYGROUP_MISC
#define KEY_Z
IMPL_LINK(CuiAboutConfigValueDialog, KeyInputHdl, const KeyEvent &, rKeyEvent, bool)
bool HasChildrenOnDemand() const
SvSortMode
Point LogicToPixel(const Point &rLogicPt) const
OUString Name
#define SAL_MIN_INT16
VclPtr< SvSimpleTableContainer > m_pPrefCtrl
bool HasChildren() const
virtual ~CuiAboutConfigTabPage() override
virtual OUString GetEntryText(SvTreeListEntry *pEntry) const override
std::vector< std::shared_ptr< Prop_Impl > > m_vectorOfModified
#define KEY_X
#define KEY_EQUAL
static std::vector< OUString > commaStringToSequence(const OUString &rCommaSepString)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString Property
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
virtual OUString GetText() const override
#define HYPER_LEN_LIMIT
RET_OK
bool IsMod1() const
#define SAL_MAX_INT16
virtual short run()
Reference< XComponentContext > getProcessComponentContext()
CuiAboutConfigTabPage(vcl::Window *pParent)
void InsertHeaderEntry(const OUString &rText, sal_uInt16 nCol=HEADERBAR_APPEND, HeaderBarItemBits nBits=HeaderBarItemBits::STDSTYLE)
virtual void dispose() override
#define SAL_WARN(area, stream)
#define KEY_POINT
static css::uno::Reference< css::container::XNameAccess > getConfigAccess(const OUString &sNodePath, bool bUpdate)
void FillItems(const css::uno::Reference< css::container::XNameAccess > &xNameAccess, SvTreeListEntry *pParentEntry=nullptr, int lineage=0, bool bLoadAll=false)
void EnableChildrenOnDemand(bool bEnable=true)