1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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>
29 #include <boost/shared_ptr.hpp>
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
44 #define ITEMID_VALUE 4
52 Prop_Impl( const OUString
& sName
, const OUString
& sProperty
, const Any
& aValue
)
54 , Property( sProperty
)
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
)
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();
77 case KEYGROUP_CURSOR
:
96 if( nKey
< KEY_ADD
|| nKey
> KEY_EQUAL
)
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
) ) )
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();
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()
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
);
201 Reference
< util::XChangesBatch
> xChangesBatch( xUpdateAccess
, UNO_QUERY_THROW
);
202 xChangesBatch
->commitChanges();
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() )
221 FillItems( xNextNameAccess
);
226 OUString sType
= aNode
.getValueTypeName();
229 switch( aNode
.getValueType().getTypeClass() )
231 case ::com::sun::star::uno::TypeClass_VOID
:
234 case ::com::sun::star::uno::TypeClass_BOOLEAN
:
235 sValue
= OUString::boolean( aNode
.get
<bool>() );
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
>() );
244 case ::com::sun::star::uno::TypeClass_DOUBLE
:
245 sValue
= OUString::number( aNode
.get
<double>() );
248 case ::com::sun::star::uno::TypeClass_STRING
:
249 sValue
= aNode
.get
<OUString
>();
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
)
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 )
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
)
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 )
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
)
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
)
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
)
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
)
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
)
364 "path \"" << sPath
<< "\" member " << seqItems
[i
]
365 << " of unsupported type " << sType
);
372 "path \"" << sPath
<< "\" member " << seqItems
[i
]
373 << " of unsupported type " << sType
);
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
;
399 sAccessString
= "com.sun.star.configuration.ConfigurationUpdateAccess";
401 sAccessString
= "com.sun.star.configuration.ConfigurationAccess";
403 uno::Reference
< container::XNameAccess
> xNameAccess(
404 xConfigProvider
->createInstanceWithArguments(
405 sAccessString
, aArgumentList
),
406 uno::UNO_QUERY_THROW
);
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;
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
;
439 OUString word
= rCommaSepString
.getToken(0, static_cast<sal_Unicode
> (','), index
);
442 tempVector
.push_back(word
);
443 }while( index
>= 0 );
447 CuiAboutConfigValueDialog::CuiAboutConfigValueDialog( Window
* pWindow
,
448 const OUString
& rValue
,
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
)
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
) ) );
477 OUString sDialogValue
;
480 if( sPropertyType
== "boolean" )
483 if( sPropertyValue
== "true" )
485 sDialogValue
= "false";
490 sDialogValue
= "true";
494 pProperty
->Value
= uno::makeAny( bValue
);
497 else if ( sPropertyType
== "void" )
503 sDialogValue
= sPropertyValue
;
511 //Cosmetic length limit for integer values.
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")
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
;
534 throw uno::Exception();
535 pProperty
->Value
= uno::makeAny( nShort
);
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
);
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
);
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
);
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
);
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
)));
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
& )
658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */