Bump version to 4.3-4
[LibreOffice.git] / cui / source / options / optaboutconfig.cxx
blob8bc67e8d263cadaa30e6ba88a6296051386f8bf0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include "optaboutconfig.hxx"
11 #include "optHeaderTabListbox.hxx"
13 #include <svtools/svlbitm.hxx>
14 #include <svtools/treelistentry.hxx>
15 #include <comphelper/processfactory.hxx>
16 #include <comphelper/sequence.hxx>
17 #include <com/sun/star/configuration/theDefaultProvider.hpp>
18 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
19 #include <com/sun/star/beans/NamedValue.hpp>
20 #include <com/sun/star/beans/Property.hpp>
21 #include <com/sun/star/beans/XProperty.hpp>
22 #include <com/sun/star/container/XNameAccess.hpp>
23 #include <com/sun/star/container/XNameReplace.hpp>
24 #include <com/sun/star/container/XHierarchicalName.hpp>
25 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
26 #include <com/sun/star/util/XChangesBatch.hpp>
28 #include <vector>
29 #include <boost/shared_ptr.hpp>
30 #include <iostream>
32 using namespace svx;
33 using namespace ::com::sun::star;
34 using namespace com::sun::star::uno;
35 using namespace com::sun::star::container;
37 #define SHORT_LEN_LIMIT 7
38 #define LONG_LEN_LIMIT 11
39 #define HYPER_LEN_LIMIT 20
41 #define ITEMID_PREFNAME 1
42 #define ITEMID_PROPERTY 2
43 #define ITEMID_TYPE 3
44 #define ITEMID_VALUE 4
46 struct Prop_Impl
48 OUString Name;
49 OUString Property;
50 Any Value;
52 Prop_Impl( const OUString& sName, const OUString& sProperty, const Any& aValue )
53 : Name( sName )
54 , Property( sProperty )
55 , Value( aValue )
59 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeCuiCustomMultilineEdit(Window *pParent, VclBuilder::stringmap &)
61 return new CuiCustomMultilineEdit(pParent, WB_LEFT|WB_VCENTER|WB_BORDER|WB_3DLOOK);
65 void CuiCustomMultilineEdit::KeyInput( const KeyEvent& rKeyEvent )
67 bool bValid = false;
68 bool bNonSpace = rKeyEvent.GetKeyCode().GetCode() != KEY_SPACE;
69 if( bNumericOnly && bNonSpace )
71 const KeyCode& rKeyCode = rKeyEvent.GetKeyCode();
72 sal_uInt16 nGroup = rKeyCode.GetGroup();
73 sal_uInt16 nKey = rKeyCode.GetCode();
75 switch ( nGroup ) {
76 case KEYGROUP_NUM :
77 case KEYGROUP_CURSOR :
79 bValid = true;
80 break;
83 case KEYGROUP_MISC :
85 switch ( nKey ) {
86 case KEY_SUBTRACT :
87 case KEY_COMMA :
88 case KEY_POINT :
90 bValid = true;
91 break;
94 default :
96 if( nKey < KEY_ADD || nKey > KEY_EQUAL )
97 bValid = true;
98 break;
101 break;
104 default :
106 bValid = false;
107 break;
111 //Select all, Copy, Paste, Cut, Undo Keys
112 if ( !bValid && ( rKeyCode.IsMod1() && (
113 KEY_A == nKey || KEY_C == nKey || KEY_V == nKey || KEY_X == nKey || KEY_Z == nKey ) ) )
114 bValid = true;
116 else
117 bValid = true;
118 if( bValid )
119 Edit::KeyInput( rKeyEvent );
122 Size CuiCustomMultilineEdit::GetOptimalSize() const
124 return LogicToPixel(Size(150, GetTextHeight()), MAP_APPFONT);
127 CuiAboutConfigTabPage::CuiAboutConfigTabPage( Window* pParent/*, const SfxItemSet& rItemSet*/ ) :
128 ModalDialog( pParent, "AboutConfig", "cui/ui/aboutconfigdialog.ui"),
129 m_pPrefCtrl( get<SvSimpleTableContainer>("preferences") ),
130 m_pResetBtn( get<PushButton>("reset") ),
131 m_pEditBtn( get<PushButton>("edit") ),
132 m_vectorOfModified(),
133 m_pPrefBox( new SvSimpleTable(*m_pPrefCtrl,
134 WB_SCROLL | WB_HSCROLL | WB_VSCROLL ) )
136 Size aControlSize(LogicToPixel(Size(385, 230), MAP_APPFONT));
137 m_pPrefCtrl->set_width_request(aControlSize.Width());
138 m_pPrefCtrl->set_height_request(aControlSize.Height());
140 m_pEditBtn->SetClickHdl( LINK( this, CuiAboutConfigTabPage, StandardHdl_Impl ) );
141 m_pResetBtn->SetClickHdl( LINK( this, CuiAboutConfigTabPage, ResetBtnHdl_Impl ) );
142 m_pPrefBox->SetDoubleClickHdl( LINK(this, CuiAboutConfigTabPage, StandardHdl_Impl) );
144 HeaderBar &rBar = m_pPrefBox->GetTheHeaderBar();
145 rBar.InsertItem( ITEMID_PREFNAME, get<FixedText>("preference")->GetText(), 0, HIB_LEFT | HIB_VCENTER );
146 rBar.InsertItem( ITEMID_PROPERTY, get<FixedText>("property")->GetText(), 0, HIB_LEFT | HIB_VCENTER );
147 rBar.InsertItem( ITEMID_TYPE, get<FixedText>("type")->GetText(), 0, HIB_LEFT | HIB_VCENTER );
148 rBar.InsertItem( ITEMID_VALUE, get<FixedText>("value")->GetText(), 0, HIB_LEFT | HIB_VCENTER );
150 long aTabs[] = {4,0,0,0,0};
152 float fWidth = approximate_char_width();
154 aTabs[1] = 0;
155 aTabs[2] = aTabs[1] + fWidth * 65;
156 aTabs[3] = aTabs[2] + fWidth * 20;
157 aTabs[4] = aTabs[3] + fWidth * 8;
159 m_pPrefBox->SetTabs(aTabs, MAP_PIXEL);
162 void CuiAboutConfigTabPage::InsertEntry(const OUString& rProp, const OUString& rStatus, const OUString& rType, const OUString& rValue)
164 SvTreeListEntry* pEntry = new SvTreeListEntry;
166 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), false)); //It is needed, otherwise causes crash
167 pEntry->AddItem( new SvLBoxString( pEntry, 0, rProp));
168 pEntry->AddItem( new SvLBoxString( pEntry, 0, rStatus));
169 pEntry->AddItem( new SvLBoxString( pEntry, 0, rType));
170 pEntry->AddItem( new SvLBoxString( pEntry, 0, rValue));
172 m_pPrefBox->Insert( pEntry );
175 void CuiAboutConfigTabPage::Reset()
177 m_pPrefBox->Clear();
179 m_vectorOfModified.clear();
180 m_pPrefBox->GetModel()->SetSortMode( SortNone );
182 m_pPrefBox->SetUpdateMode(false);
183 Reference< XNameAccess > xConfigAccess = getConfigAccess( "/", false );
184 FillItems( xConfigAccess );
185 m_pPrefBox->SetUpdateMode(true);
188 bool CuiAboutConfigTabPage::FillItemSet()
190 bool bModified = false;
192 std::vector< boost::shared_ptr< Prop_Impl > >::iterator pIter;
193 for( pIter = m_vectorOfModified.begin() ; pIter != m_vectorOfModified.end(); ++pIter )
195 Reference< XNameAccess > xUpdateAccess = getConfigAccess( (*pIter)->Name , true );
196 Reference< XNameReplace > xNameReplace( xUpdateAccess, UNO_QUERY_THROW );
198 xNameReplace->replaceByName( (*pIter)->Property, (*pIter)->Value );
199 bModified = true;
201 Reference< util::XChangesBatch > xChangesBatch( xUpdateAccess, UNO_QUERY_THROW );
202 xChangesBatch->commitChanges();
205 return bModified;
208 void CuiAboutConfigTabPage::FillItems(const Reference< XNameAccess >& xNameAccess)
210 OUString sPath = Reference< XHierarchicalName >(
211 xNameAccess, uno::UNO_QUERY_THROW )->getHierarchicalName();
212 uno::Sequence< OUString > seqItems = xNameAccess->getElementNames();
213 for( sal_Int32 i = 0; i < seqItems.getLength(); ++i )
215 Any aNode = xNameAccess->getByName( seqItems[i] );
217 Reference< XNameAccess > xNextNameAccess( aNode, uno::UNO_QUERY );
218 if( xNextNameAccess.is() )
220 // not leaf node
221 FillItems( xNextNameAccess );
223 else
225 // leaf node
226 OUString sType = aNode.getValueTypeName();
228 OUString sValue;
229 switch( aNode.getValueType().getTypeClass() )
231 case ::com::sun::star::uno::TypeClass_VOID:
232 break;
234 case ::com::sun::star::uno::TypeClass_BOOLEAN:
235 sValue = OUString::boolean( aNode.get<bool>() );
236 break;
238 case ::com::sun::star::uno::TypeClass_SHORT:
239 case ::com::sun::star::uno::TypeClass_LONG:
240 case ::com::sun::star::uno::TypeClass_HYPER:
241 sValue = OUString::number( aNode.get<sal_Int64>() );
242 break;
244 case ::com::sun::star::uno::TypeClass_DOUBLE:
245 sValue = OUString::number( aNode.get<double>() );
246 break;
248 case ::com::sun::star::uno::TypeClass_STRING:
249 sValue = aNode.get<OUString>();
250 break;
252 case ::com::sun::star::uno::TypeClass_SEQUENCE:
253 if( sType == "[]boolean" )
255 uno::Sequence<sal_Bool> seq = aNode.get< uno::Sequence<sal_Bool> >();
256 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
258 if( j != 0 )
260 sValue += ",";
262 sValue += OUString::boolean( seq[j] );
265 else if( sType == "[]byte" )
267 uno::Sequence<sal_Int8> seq = aNode.get< uno::Sequence<sal_Int8> >();
268 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
270 OUString s = OUString::number(
271 static_cast<sal_uInt8>(seq[j]), 16 );
272 if( s.getLength() == 1 )
274 sValue += "0";
276 sValue += s.toAsciiUpperCase();
279 else if( sType == "[][]byte" )
281 uno::Sequence< uno::Sequence<sal_Int8> > seq = aNode.get< uno::Sequence< uno::Sequence<sal_Int8> > >();
282 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
284 if( j != 0 )
286 sValue += ",";
288 for( sal_Int32 k = 0; k != seq[j].getLength(); ++k )
290 OUString s = OUString::number(
291 static_cast<sal_uInt8>(seq[j][k]), 16 );
292 if( s.getLength() == 1 )
294 sValue += "0";
296 sValue += s.toAsciiUpperCase();
300 else if( sType == "[]short" )
302 uno::Sequence<sal_Int16> seq = aNode.get< uno::Sequence<sal_Int16> >();
303 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
305 if( j != 0 )
307 sValue += ",";
309 sValue += OUString::number( seq[j] );
312 else if( sType == "[]long" )
314 uno::Sequence<sal_Int32> seq = aNode.get< uno::Sequence<sal_Int32> >();
315 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
317 if( j != 0 )
319 sValue += ",";
321 sValue += OUString::number( seq[j] );
324 else if( sType == "[]hyper" )
326 uno::Sequence<sal_Int64> seq = aNode.get< uno::Sequence<sal_Int64> >();
327 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
329 if( j != 0 )
331 sValue += ",";
333 sValue += OUString::number( seq[j] );
336 else if( sType == "[]double" )
338 uno::Sequence<double> seq = aNode.get< uno::Sequence<double> >();
339 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
341 if( j != 0 )
343 sValue += ",";
345 sValue += OUString::number( seq[j] );
348 else if( sType == "[]string" )
350 uno::Sequence<OUString> seq = aNode.get< uno::Sequence<OUString> >();
351 for( sal_Int32 j = 0; j != seq.getLength(); ++j )
353 if( j != 0 )
355 sValue += ",";
357 sValue += seq[j];
360 else
362 SAL_WARN(
363 "cui.options",
364 "path \"" << sPath << "\" member " << seqItems[i]
365 << " of unsupported type " << sType);
367 break;
369 default:
370 SAL_WARN(
371 "cui.options",
372 "path \"" << sPath << "\" member " << seqItems[i]
373 << " of unsupported type " << sType);
374 break;
377 InsertEntry( sPath, seqItems[i], sType, sValue);
382 Reference< XNameAccess > CuiAboutConfigTabPage::getConfigAccess( const OUString& sNodePath, bool bUpdate )
384 uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
386 uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
387 com::sun::star::configuration::theDefaultProvider::get( xContext ) );
389 beans::NamedValue aProperty;
390 aProperty.Name = "nodepath";
391 aProperty.Value = uno::makeAny( sNodePath );
393 uno::Sequence< uno::Any > aArgumentList( 1 );
394 aArgumentList[0] = uno::makeAny( aProperty );
396 OUString sAccessString;
398 if( bUpdate )
399 sAccessString = "com.sun.star.configuration.ConfigurationUpdateAccess";
400 else
401 sAccessString = "com.sun.star.configuration.ConfigurationAccess";
403 uno::Reference< container::XNameAccess > xNameAccess(
404 xConfigProvider->createInstanceWithArguments(
405 sAccessString, aArgumentList ),
406 uno::UNO_QUERY_THROW );
408 return xNameAccess;
411 void CuiAboutConfigTabPage::AddToModifiedVector( const boost::shared_ptr< Prop_Impl >& rProp )
413 bool isModifiedBefore = false;
414 //Check if value modified before
415 for( size_t nInd = 0; nInd < m_vectorOfModified.size() ; ++nInd )
417 if( rProp->Name == m_vectorOfModified[nInd]->Name && rProp->Property == m_vectorOfModified[nInd]->Property )
419 //property modified before. assing reference to the modified value
420 //do your changes on this object. They will be saved later.
421 m_vectorOfModified[nInd] = rProp;
422 isModifiedBefore = true;
423 break;
427 if( !isModifiedBefore )
428 m_vectorOfModified.push_back( rProp );
429 //property is not modified before
432 std::vector< OUString > CuiAboutConfigTabPage::commaStringToSequence( const OUString& rCommaSepString )
434 std::vector<OUString> tempVector;
436 sal_Int32 index = 0;
439 OUString word = rCommaSepString.getToken(0, static_cast<sal_Unicode> (','), index);
440 word = word.trim();
441 if( !word.isEmpty())
442 tempVector.push_back(word);
443 }while( index >= 0 );
444 return tempVector;
447 CuiAboutConfigValueDialog::CuiAboutConfigValueDialog( Window* pWindow,
448 const OUString& rValue,
449 int limit ) :
450 ModalDialog( pWindow, "AboutConfigValueDialog", "cui/ui/aboutconfigvaluedialog.ui" ),
451 m_pEDValue( get<CuiCustomMultilineEdit>("valuebox") )
453 m_pEDValue->bNumericOnly = ( limit !=0 );
454 m_pEDValue->SetMaxTextLen( limit == 0 ? EDIT_NOLIMIT : limit);
455 m_pEDValue->SetText( rValue );
459 IMPL_LINK_NOARG( CuiAboutConfigTabPage, ResetBtnHdl_Impl )
461 Reset();
462 return 0;
465 IMPL_LINK_NOARG( CuiAboutConfigTabPage, StandardHdl_Impl )
467 SvTreeListEntry* pEntry = m_pPrefBox->FirstSelected();
469 OUString sPropertyPath = m_pPrefBox->GetEntryText( pEntry, 0 );
470 OUString sPropertyName = m_pPrefBox->GetEntryText( pEntry, 1 );
471 OUString sPropertyType = m_pPrefBox->GetEntryText( pEntry, 2 );
472 OUString sPropertyValue = m_pPrefBox->GetEntryText( pEntry, 3 );
474 boost::shared_ptr< Prop_Impl > pProperty (new Prop_Impl( sPropertyPath, sPropertyName, makeAny( sPropertyValue ) ) );
476 bool bOpenDialog;
477 OUString sDialogValue;
478 OUString sNewValue;
480 if( sPropertyType == "boolean" )
482 bool bValue;
483 if( sPropertyValue == "true" )
485 sDialogValue = "false";
486 bValue = false;
488 else
490 sDialogValue = "true";
491 bValue = true;
494 pProperty->Value = uno::makeAny( bValue );
495 bOpenDialog = false;
497 else if ( sPropertyType == "void" )
499 bOpenDialog = false;
501 else
503 sDialogValue = sPropertyValue;
504 bOpenDialog = true;
509 if( bOpenDialog )
511 //Cosmetic length limit for integer values.
512 int limit=0;
513 if( sPropertyType == "short" )
514 limit = SHORT_LEN_LIMIT;
515 else if( sPropertyType == "long" )
516 limit = LONG_LEN_LIMIT;
517 else if( sPropertyType == "hyper" )
518 limit = HYPER_LEN_LIMIT;
520 CuiAboutConfigValueDialog* pValueDialog = new CuiAboutConfigValueDialog(0, sDialogValue, limit);
522 if( pValueDialog->Execute() == RET_OK )
524 sNewValue = pValueDialog->getValue();
525 if ( sPropertyType == "short")
527 sal_Int16 nShort;
528 sal_Int32 nNumb = sNewValue.toInt32();
530 //if the value is 0 and length is not 1, there is something wrong
531 if( !( nNumb==0 && sNewValue.getLength()!=1 ) && nNumb < SAL_MAX_INT16 && nNumb > SAL_MIN_INT16)
532 nShort = (sal_Int16) nNumb;
533 else
534 throw uno::Exception();
535 pProperty->Value = uno::makeAny( nShort );
537 else
538 if( sPropertyType == "long" )
540 sal_Int32 nLong = sNewValue.toInt32();
541 if( !( nLong==0 && sNewValue.getLength()!=1 ) && nLong < SAL_MAX_INT32 && nLong > SAL_MIN_INT32)
542 pProperty->Value = uno::makeAny( nLong );
543 else
544 throw uno::Exception();
546 else if( sPropertyType == "hyper")
548 sal_Int64 nHyper = sNewValue.toInt64();
549 if( !( nHyper==0 && sNewValue.getLength()!=1 ) && nHyper < SAL_MAX_INT32 && nHyper > SAL_MIN_INT32)
550 pProperty->Value = uno::makeAny( nHyper );
551 else
552 throw uno::Exception();
554 else if( sPropertyType == "double")
556 double nDoub = sNewValue.toDouble();
557 if( !( nDoub ==0 && sNewValue.getLength()!=1 ) && nDoub < SAL_MAX_INT32 && nDoub > SAL_MIN_INT32)
558 pProperty->Value = uno::makeAny( nDoub );
559 else
560 throw uno::Exception();
562 else if( sPropertyType == "float")
564 float nFloat = sNewValue.toFloat();
565 if( !( nFloat ==0 && sNewValue.getLength()!=1 ) && nFloat < SAL_MAX_INT32 && nFloat > SAL_MIN_INT32)
566 pProperty->Value = uno::makeAny( nFloat );
567 else
568 throw uno::Exception();
570 else if( sPropertyType == "string" )
572 pProperty->Value = uno::makeAny( sNewValue );
574 else if( sPropertyType == "[]short" )
576 //create string sequence from comma separated string
577 //uno::Sequence< OUString > seqStr;
578 std::vector< OUString > seqStr;
579 seqStr = commaStringToSequence( sNewValue );
581 //create appropriate sequence with same size as string sequence
582 uno::Sequence< sal_Int16 > seqShort( seqStr.size() );
583 //convert all strings to appropriate type
584 for( size_t i = 0; i < seqStr.size(); ++i )
586 seqShort[i] = (sal_Int16) seqStr[i].toInt32();
588 pProperty->Value = uno::makeAny( seqShort );
590 else if( sPropertyType == "[]long" )
592 std::vector< OUString > seqStrLong;
593 seqStrLong = commaStringToSequence( sNewValue );
595 uno::Sequence< sal_Int32 > seqLong( seqStrLong.size() );
596 for( size_t i = 0; i < seqStrLong.size(); ++i )
598 seqLong[i] = seqStrLong[i].toInt32();
600 pProperty->Value = uno::makeAny( seqLong );
602 else if( sPropertyType == "[]hyper" )
604 std::vector< OUString > seqStrHyper;
605 seqStrHyper = commaStringToSequence( sNewValue );
606 uno::Sequence< sal_Int64 > seqHyper( seqStrHyper.size() );
607 for( size_t i = 0; i < seqStrHyper.size(); ++i )
609 seqHyper[i] = seqStrHyper[i].toInt64();
611 pProperty->Value = uno::makeAny( seqHyper );
613 else if( sPropertyType == "[]double" )
615 std::vector< OUString > seqStrDoub;
616 seqStrDoub = commaStringToSequence( sNewValue );
617 uno::Sequence< double > seqDoub( seqStrDoub.size() );
618 for( size_t i = 0; i < seqStrDoub.size(); ++i )
620 seqDoub[i] = seqStrDoub[i].toDouble();
622 pProperty->Value = uno::makeAny( seqDoub );
624 else if( sPropertyType == "[]float" )
626 std::vector< OUString > seqStrFloat;
627 seqStrFloat = commaStringToSequence( sNewValue );
628 uno::Sequence< sal_Int16 > seqFloat( seqStrFloat.size() );
629 for( size_t i = 0; i < seqStrFloat.size(); ++i )
631 seqFloat[i] = seqStrFloat[i].toFloat();
633 pProperty->Value = uno::makeAny( seqFloat );
635 else if( sPropertyType == "[]string" )
637 pProperty->Value = uno::makeAny( comphelper::containerToSequence( commaStringToSequence( sNewValue )));
639 else //unknown
640 throw uno::Exception();
643 sDialogValue = sNewValue;
646 AddToModifiedVector( pProperty );
648 //update listbox value.
649 m_pPrefBox->SetEntryText( sDialogValue, pEntry, 3 );
651 catch( uno::Exception& )
655 return 0;
658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */