xref: /trunk/main/cui/source/options/optpath.cxx (revision 09db6d69)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cui.hxx"
26 
27 // include ---------------------------------------------------------------
28 
29 #include <svx/svxdlg.hxx>
30 #include <tools/shl.hxx>
31 #include <vcl/msgbox.hxx>
32 #include <sfx2/filedlghelper.hxx>
33 #include <sfx2/app.hxx>
34 #include <svl/aeitem.hxx>
35 #include <svtools/svtabbx.hxx>
36 #include <svtools/filedlg.hxx>
37 #include <tools/config.hxx>
38 #include <tools/urlobj.hxx>
39 #include <vcl/svapp.hxx>
40 #include <unotools/defaultoptions.hxx>
41 #include <unotools/localfilehelper.hxx>
42 #include <unotools/pathoptions.hxx>
43 #include <unotools/moduleoptions.hxx>
44 #include <unotools/viewoptions.hxx>
45 
46 #define _SVX_OPTPATH_CXX
47 
48 #include "optpath.hxx"
49 #include <dialmgr.hxx>
50 #include "optpath.hrc"
51 #include <cuires.hrc>
52 #include "helpid.hrc"
53 #include <comphelper/processfactory.hxx>
54 #include <comphelper/configurationhelper.hxx>
55 #include <com/sun/star/uno/Exception.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/beans/PropertyAttribute.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
60 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
61 #include "optHeaderTabListbox.hxx"
62 #include <readonlyimage.hxx>
63 #include <vcl/help.hxx>
64 
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::lang;
67 using namespace ::com::sun::star::ui::dialogs;
68 using namespace ::com::sun::star::uno;
69 using namespace svx;
70 
71 // define ----------------------------------------------------------------
72 
73 #define TAB_WIDTH1		80
74 #define TAB_WIDTH_MIN   10
75 #define TAB_WIDTH2		1000
76 #define ITEMID_TYPE       1
77 #define ITEMID_PATH       2
78 
79 #define POSTFIX_INTERNAL    String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "_internal" ) )
80 #define POSTFIX_USER        String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "_user" ) )
81 #define POSTFIX_WRITABLE    String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "_writable" ) )
82 #define POSTFIX_READONLY    String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "_readonly" ) )
83 #define VAR_ONE             String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "%1" ) )
84 #define IODLG_CONFIGNAME	String(DEFINE_CONST_UNICODE("FilePicker_Save"))
85 
86 // struct OptPath_Impl ---------------------------------------------------
87 
88 struct OptPath_Impl
89 {
90     SvtDefaultOptions           m_aDefOpt;
91     Image                       m_aLockImage;
92     Image                       m_aLockImageHC;
93     String                      m_sMultiPathDlg;
94     Reference< XPropertySet >   m_xPathSettings;
95 
OptPath_ImplOptPath_Impl96     OptPath_Impl(const ResId& rLockRes, const ResId& rLockResHC) :
97         m_aLockImage(rLockRes),
98         m_aLockImageHC(rLockResHC){}
99 };
100 
101 // struct PathUserData_Impl ----------------------------------------------
102 
103 struct PathUserData_Impl
104 {
105     sal_uInt16          nRealId;
106     SfxItemState    eState;
107     String          sUserPath;
108     String          sWritablePath;
109 
PathUserData_ImplPathUserData_Impl110     PathUserData_Impl( sal_uInt16 nId ) :
111         nRealId( nId ), eState( SFX_ITEM_UNKNOWN ) {}
112 };
113 
114 struct Handle2CfgNameMapping_Impl
115 {
116     sal_uInt16      m_nHandle;
117     const char* m_pCfgName;
118 };
119 
120 static Handle2CfgNameMapping_Impl __READONLY_DATA Hdl2CfgMap_Impl[] =
121 {
122     { SvtPathOptions::PATH_AUTOCORRECT, "AutoCorrect" },
123     { SvtPathOptions::PATH_AUTOTEXT,    "AutoText" },
124     { SvtPathOptions::PATH_BACKUP,      "Backup" },
125     { SvtPathOptions::PATH_GALLERY,     "Gallery" },
126     { SvtPathOptions::PATH_GRAPHIC,     "Graphic" },
127     { SvtPathOptions::PATH_TEMP,        "Temp" },
128     { SvtPathOptions::PATH_TEMPLATE,    "Template" },
129     { SvtPathOptions::PATH_WORK,        "Work" },
130 #if OSL_DEBUG_LEVEL > 1
131     { SvtPathOptions::PATH_LINGUISTIC,        "Linguistic" },
132     { SvtPathOptions::PATH_DICTIONARY,        "Dictionary" },
133 #endif
134     { USHRT_MAX, NULL }
135 };
136 
getCfgName_Impl(sal_uInt16 _nHandle)137 static String getCfgName_Impl( sal_uInt16 _nHandle )
138 {
139     String sCfgName;
140     sal_uInt16 nIndex = 0;
141     while ( Hdl2CfgMap_Impl[ nIndex ].m_nHandle != USHRT_MAX )
142     {
143         if ( Hdl2CfgMap_Impl[ nIndex ].m_nHandle == _nHandle )
144         {
145             // config name found
146             sCfgName = String::CreateFromAscii( Hdl2CfgMap_Impl[ nIndex ].m_pCfgName );
147             break;
148         }
149         ++nIndex;
150     }
151 
152     return sCfgName;
153 }
154 
155 #define MULTIPATH_DELIMITER     ';'
156 
Convert_Impl(const String & rValue)157 String Convert_Impl( const String& rValue )
158 {
159 	char cDelim = MULTIPATH_DELIMITER;
160     sal_uInt16 nCount = rValue.GetTokenCount( cDelim );
161     String aReturn;
162     for ( sal_uInt16 i=0; i<nCount ; ++i )
163 	{
164         String aValue = rValue.GetToken( i, cDelim );
165         INetURLObject aObj( aValue );
166         if ( aObj.GetProtocol() == INET_PROT_FILE )
167             aReturn += String(aObj.PathToFileName());
168         else if ( ::utl::LocalFileHelper::IsFileContent( aValue ) )
169             aReturn += String(aObj.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ));
170         if ( i+1 < nCount)
171             aReturn += MULTIPATH_DELIMITER;
172     }
173 
174     return aReturn;
175 }
176 
177 // class SvxControlFocusHelper ---------------------------------------------
178 
Notify(NotifyEvent & rNEvt)179 long SvxControlFocusHelper::Notify( NotifyEvent& rNEvt )
180 {
181 	long nRet = Control::Notify( rNEvt );
182 
183 	if ( m_pFocusCtrl && rNEvt.GetWindow() != m_pFocusCtrl && rNEvt.GetType() == EVENT_GETFOCUS )
184 		m_pFocusCtrl->GrabFocus();
185 	return nRet;
186 }
187 
188 // functions -------------------------------------------------------------
189 
IsMultiPath_Impl(const sal_uInt16 nIndex)190 sal_Bool IsMultiPath_Impl( const sal_uInt16 nIndex )
191 {
192 #if OSL_DEBUG_LEVEL > 1
193 	return ( SvtPathOptions::PATH_AUTOCORRECT == nIndex ||
194 			 SvtPathOptions::PATH_AUTOTEXT == nIndex ||
195 			 SvtPathOptions::PATH_BASIC == nIndex ||
196 			 SvtPathOptions::PATH_GALLERY == nIndex ||
197 			 SvtPathOptions::PATH_TEMPLATE == nIndex );
198 #else
199     return ( SvtPathOptions::PATH_AUTOCORRECT == nIndex ||
200              SvtPathOptions::PATH_AUTOTEXT == nIndex ||
201              SvtPathOptions::PATH_BASIC == nIndex ||
202              SvtPathOptions::PATH_GALLERY == nIndex ||
203              SvtPathOptions::PATH_TEMPLATE == nIndex ||
204              SvtPathOptions::PATH_LINGUISTIC == nIndex ||
205              SvtPathOptions::PATH_DICTIONARY == nIndex  );
206 #endif
207 }
208 
209 // class SvxPathTabPage --------------------------------------------------
210 
SvxPathTabPage(Window * pParent,const SfxItemSet & rSet)211 SvxPathTabPage::SvxPathTabPage( Window* pParent, const SfxItemSet& rSet ) :
212 
213 	SfxTabPage( pParent, CUI_RES( RID_SFXPAGE_PATH ), rSet ),
214 
215 	aStdBox			( this, CUI_RES( GB_STD ) ),
216 	aTypeText		( this, CUI_RES( FT_TYPE ) ),
217 	aPathText		( this, CUI_RES( FT_PATH ) ),
218 	aPathCtrl		( this, CUI_RES( LB_PATH ) ),
219 	aStandardBtn	( this, CUI_RES( BTN_STANDARD ) ),
220 	aPathBtn		( this, CUI_RES( BTN_PATH ) ),
221 	pHeaderBar		( NULL ),
222 	pPathBox		( NULL ),
223     pImpl           ( new OptPath_Impl( CUI_RES(IMG_LOCK), CUI_RES(IMG_LOCK_HC) ) ),
224     xDialogListener ( new ::svt::DialogClosedListener() )
225 
226 {
227     pImpl->m_sMultiPathDlg = String( CUI_RES( STR_MULTIPATHDLG ) );
228 	aStandardBtn.SetClickHdl( LINK( this, SvxPathTabPage, StandardHdl_Impl ) );
229 	Link aLink = LINK( this, SvxPathTabPage, PathHdl_Impl );
230 	aPathBtn.SetClickHdl( aLink );
231 	Size aBoxSize = aPathCtrl.GetOutputSizePixel();
232 	pHeaderBar = new HeaderBar( &aPathCtrl, WB_BUTTONSTYLE | WB_BOTTOMBORDER );
233 	pHeaderBar->SetPosSizePixel( Point( 0, 0 ), Size( aBoxSize.Width(), 20 ) );
234 	pHeaderBar->SetSelectHdl( LINK( this, SvxPathTabPage, HeaderSelect_Impl ) );
235 	pHeaderBar->SetEndDragHdl( LINK( this, SvxPathTabPage, HeaderEndDrag_Impl ) );
236 	Size aSz;
237 	aSz.Width() = TAB_WIDTH1;
238 	pHeaderBar->InsertItem( ITEMID_TYPE, aTypeText.GetText(),
239 							LogicToPixel( aSz, MapMode( MAP_APPFONT ) ).Width(),
240 							HIB_LEFT | HIB_VCENTER | HIB_CLICKABLE | HIB_UPARROW );
241 	aSz.Width() = TAB_WIDTH2;
242 	pHeaderBar->InsertItem( ITEMID_PATH, aPathText.GetText(),
243 							LogicToPixel( aSz, MapMode( MAP_APPFONT ) ).Width(),
244 							HIB_LEFT | HIB_VCENTER );
245 
246 	static long nTabs[] = {3, 0, TAB_WIDTH1, TAB_WIDTH1 + TAB_WIDTH2 };
247 	Size aHeadSize = pHeaderBar->GetSizePixel();
248 
249 	WinBits nBits = WB_SORT | WB_HSCROLL | WB_CLIPCHILDREN | WB_TABSTOP;
250 	pPathBox = new svx::OptHeaderTabListBox( &aPathCtrl, nBits );
251 	aPathCtrl.SetFocusControl( pPathBox );
252 	pPathBox->SetDoubleClickHdl( aLink );
253 	pPathBox->SetSelectHdl( LINK( this, SvxPathTabPage, PathSelect_Impl ) );
254 	pPathBox->SetSelectionMode( MULTIPLE_SELECTION );
255 	pPathBox->SetPosSizePixel( Point( 0, aHeadSize.Height() ),
256 							   Size( aBoxSize.Width(), aBoxSize.Height() - aHeadSize.Height() ) );
257 	pPathBox->SetTabs( &nTabs[0], MAP_APPFONT );
258 	pPathBox->InitHeaderBar( pHeaderBar );
259 	pPathBox->SetHighlightRange();
260 	pPathBox->SetHelpId( HID_OPTPATH_CTL_PATH );
261 	pHeaderBar->SetHelpId( HID_OPTPATH_HEADERBAR );
262 	pPathBox->Show();
263 	pHeaderBar->Show();
264 
265 	FreeResource();
266 
267     xDialogListener->SetDialogClosedLink( LINK( this, SvxPathTabPage, DialogClosedHdl ) );
268 }
269 
270 // -----------------------------------------------------------------------
271 
~SvxPathTabPage()272 SvxPathTabPage::~SvxPathTabPage()
273 {
274     // #110603# do not grab focus to a destroyed window !!!
275     aPathCtrl.SetFocusControl( NULL );
276 
277 	pHeaderBar->Hide();
278 	for ( sal_uInt16 i = 0; i < pPathBox->GetEntryCount(); ++i )
279 		delete (PathUserData_Impl*)pPathBox->GetEntry(i)->GetUserData();
280 	delete pPathBox;
281 	delete pHeaderBar;
282 	delete pImpl;
283 }
284 
285 // -----------------------------------------------------------------------
286 
Create(Window * pParent,const SfxItemSet & rAttrSet)287 SfxTabPage*	SvxPathTabPage::Create( Window* pParent,
288 									const SfxItemSet& rAttrSet )
289 {
290 	return ( new SvxPathTabPage( pParent, rAttrSet ) );
291 }
292 
293 // -----------------------------------------------------------------------
294 
FillItemSet(SfxItemSet &)295 sal_Bool SvxPathTabPage::FillItemSet( SfxItemSet& )
296 {
297     SvtPathOptions aPathOpt;
298     for ( sal_uInt16 i = 0; i < pPathBox->GetEntryCount(); ++i )
299     {
300 		PathUserData_Impl* pPathImpl = (PathUserData_Impl*)pPathBox->GetEntry(i)->GetUserData();
301 		sal_uInt16 nRealId = pPathImpl->nRealId;
302         if ( pPathImpl->eState == SFX_ITEM_SET )
303             SetPathList( nRealId, pPathImpl->sUserPath, pPathImpl->sWritablePath );
304     }
305 	return sal_True;
306 }
307 
308 // -----------------------------------------------------------------------
309 
Reset(const SfxItemSet &)310 void SvxPathTabPage::Reset( const SfxItemSet& )
311 {
312     pPathBox->Clear();
313     SvtPathOptions aPathOpt; //! deprecated
314 
315     for( sal_uInt16 i = 0; i <= (sal_uInt16)SvtPathOptions::PATH_WORK; ++i )
316     {
317         // only writer uses autotext
318         if ( i == SvtPathOptions::PATH_AUTOTEXT
319             && !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
320             continue;
321 
322         switch (i)
323         {
324             case SvtPathOptions::PATH_AUTOCORRECT:
325             case SvtPathOptions::PATH_AUTOTEXT:
326             case SvtPathOptions::PATH_BACKUP:
327             case SvtPathOptions::PATH_GALLERY:
328             case SvtPathOptions::PATH_GRAPHIC:
329             case SvtPathOptions::PATH_TEMP:
330             case SvtPathOptions::PATH_TEMPLATE:
331 #if OSL_DEBUG_LEVEL > 1
332             case SvtPathOptions::PATH_LINGUISTIC:
333             case SvtPathOptions::PATH_DICTIONARY:
334 #endif
335             case SvtPathOptions::PATH_WORK:
336             {
337                 String aStr( CUI_RES( RID_SVXSTR_PATH_NAME_START + i ) );
338                 String sInternal, sUser, sWritable;
339                 sal_Bool bReadOnly = sal_False;
340                 GetPathList( i, sInternal, sUser, sWritable, bReadOnly );
341                 String sTmpPath = sUser;
342                 if ( sTmpPath.Len() > 0 && sWritable.Len() > 0 )
343                     sTmpPath += MULTIPATH_DELIMITER;
344                 sTmpPath += sWritable;
345                 String aValue( sTmpPath );
346                 aStr += '\t';
347                 aStr += Convert_Impl( aValue );
348                 SvLBoxEntry* pEntry = pPathBox->InsertEntry( aStr );
349                 if ( bReadOnly )
350                 {
351                     pPathBox->SetCollapsedEntryBmp( pEntry, pImpl->m_aLockImage, BMP_COLOR_NORMAL );
352                     pPathBox->SetCollapsedEntryBmp( pEntry, pImpl->m_aLockImageHC, BMP_COLOR_HIGHCONTRAST );
353                 }
354                 PathUserData_Impl* pPathImpl = new PathUserData_Impl(i);
355                 pPathImpl->sUserPath = sUser;
356                 pPathImpl->sWritablePath = sWritable;
357                 pEntry->SetUserData( pPathImpl );
358             }
359         }
360     }
361 
362     String aUserData = GetUserData();
363 	if ( aUserData.Len() )
364 	{
365 		// Spaltenbreite restaurieren
366 		pHeaderBar->SetItemSize( ITEMID_TYPE, aUserData.GetToken(0).ToInt32() );
367 		HeaderEndDrag_Impl( NULL );
368 		// Sortierrichtung restaurieren
369 		sal_Bool bUp = (sal_Bool)(sal_uInt16)aUserData.GetToken(1).ToInt32();
370 		HeaderBarItemBits nBits	= pHeaderBar->GetItemBits(ITEMID_TYPE);
371 
372 		if ( bUp )
373 		{
374 			nBits &= ~HIB_UPARROW;
375 			nBits |= HIB_DOWNARROW;
376 		}
377 		else
378 		{
379 			nBits &= ~HIB_DOWNARROW;
380 			nBits |= HIB_UPARROW;
381 		}
382 		pHeaderBar->SetItemBits( ITEMID_TYPE, nBits );
383 		HeaderSelect_Impl( NULL );
384 	}
385 	PathSelect_Impl( NULL );
386 }
387 
388 // -----------------------------------------------------------------------
389 
FillUserData()390 void SvxPathTabPage::FillUserData()
391 {
392 	String aUserData = String::CreateFromInt32( pHeaderBar->GetItemSize( ITEMID_TYPE ) );
393 	aUserData += ';';
394 	HeaderBarItemBits nBits	= pHeaderBar->GetItemBits( ITEMID_TYPE );
395 	sal_Bool bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
396 	aUserData += bUp ? '1' : '0';
397 	SetUserData( aUserData );
398 }
399 
400 // -----------------------------------------------------------------------
401 
IMPL_LINK(SvxPathTabPage,PathSelect_Impl,svx::OptHeaderTabListBox *,EMPTYARG)402 IMPL_LINK( SvxPathTabPage, PathSelect_Impl, svx::OptHeaderTabListBox *, EMPTYARG )
403 
404 /*	[Beschreibung]
405 
406 */
407 
408 {
409 	sal_uInt16 nSelCount = 0;
410 	SvLBoxEntry* pEntry = pPathBox->FirstSelected();
411 
412     //the entry image indicates whether the path is write protected
413     Image aEntryImage;
414     if(pEntry)
415         aEntryImage = pPathBox->GetCollapsedEntryBmp( pEntry );
416     sal_Bool bEnable = !aEntryImage;
417 	while ( pEntry && ( nSelCount < 2 ) )
418 	{
419 		nSelCount++;
420 		pEntry = pPathBox->NextSelected( pEntry );
421 	}
422 
423     aPathBtn.Enable( 1 == nSelCount && bEnable);
424     aStandardBtn.Enable( nSelCount > 0 && bEnable);
425 	return 0;
426 }
427 
428 // -----------------------------------------------------------------------
429 
IMPL_LINK(SvxPathTabPage,StandardHdl_Impl,PushButton *,EMPTYARG)430 IMPL_LINK( SvxPathTabPage, StandardHdl_Impl, PushButton *, EMPTYARG )
431 {
432 	SvLBoxEntry* pEntry = pPathBox->FirstSelected();
433 	while ( pEntry )
434 	{
435 		PathUserData_Impl* pPathImpl = (PathUserData_Impl*)pEntry->GetUserData();
436         String aOldPath = pImpl->m_aDefOpt.GetDefaultPath( pPathImpl->nRealId );
437 
438 		if ( aOldPath.Len() )
439 		{
440             String sInternal, sUser, sWritable, sTemp;
441             sal_Bool bReadOnly = sal_False;
442             GetPathList( pPathImpl->nRealId, sInternal, sUser, sWritable, bReadOnly );
443 
444             sal_uInt16 i;
445             sal_uInt16 nOldCount = aOldPath.GetTokenCount( MULTIPATH_DELIMITER );
446             sal_uInt16 nIntCount = sInternal.GetTokenCount( MULTIPATH_DELIMITER );
447             for ( i = 0; i < nOldCount; ++i )
448             {
449                 bool bFound = false;
450                 String sOnePath = aOldPath.GetToken( i, MULTIPATH_DELIMITER );
451                 for ( sal_uInt16 j = 0; !bFound && j < nIntCount; ++j )
452                 {
453                     if ( sInternal.GetToken( i, MULTIPATH_DELIMITER ) == sOnePath )
454                         bFound = true;
455                 }
456                 if ( !bFound )
457                 {
458                     if ( sTemp.Len() > 0 )
459                         sTemp += MULTIPATH_DELIMITER;
460                     sTemp += sOnePath;
461                 }
462             }
463 
464             String sUserPath, sWritablePath;
465             nOldCount = sTemp.GetTokenCount( MULTIPATH_DELIMITER );
466             for ( i = 0; nOldCount > 0 && i < nOldCount - 1; ++i )
467             {
468                 if ( sUserPath.Len() > 0 )
469                     sUserPath += MULTIPATH_DELIMITER;
470                 sUserPath += sTemp.GetToken( i, MULTIPATH_DELIMITER );
471             }
472             sWritablePath = sTemp.GetToken( nOldCount - 1, MULTIPATH_DELIMITER );
473 
474             pPathBox->SetEntryText( Convert_Impl( sTemp ), pEntry, 1 );
475 			pPathImpl->eState = SFX_ITEM_SET;
476             pPathImpl->sUserPath = sUserPath;
477             pPathImpl->sWritablePath = sWritablePath;
478 		}
479 		pEntry = pPathBox->NextSelected( pEntry );
480 	}
481 	return 0;
482 }
483 
484 // -----------------------------------------------------------------------
485 
ChangeCurrentEntry(const String & _rFolder)486 void SvxPathTabPage::ChangeCurrentEntry( const String& _rFolder )
487 {
488     SvLBoxEntry* pEntry = pPathBox->GetCurEntry();
489     if ( !pEntry )
490     {
491         DBG_ERRORFILE( "SvxPathTabPage::ChangeCurrentEntry(): no entry" );
492         return;
493     }
494 
495     String sInternal, sUser, sWritable;
496     PathUserData_Impl* pPathImpl = (PathUserData_Impl*)pEntry->GetUserData();
497     sal_Bool bReadOnly = sal_False;
498     GetPathList( pPathImpl->nRealId, sInternal, sUser, sWritable, bReadOnly );
499     sUser = pPathImpl->sUserPath;
500     sWritable = pPathImpl->sWritablePath;
501     sal_uInt16 nPos = pPathImpl->nRealId;
502 
503     // old path is an URL?
504     INetURLObject aObj( sWritable );
505     FASTBOOL bURL = ( aObj.GetProtocol() != INET_PROT_NOT_VALID );
506     rtl::OUString aPathStr( _rFolder );
507     INetURLObject aNewObj( aPathStr );
508     aNewObj.removeFinalSlash();
509 
510     // then the new path also an URL else system path
511     String sNewPathStr = bURL ? aPathStr : aNewObj.getFSysPath( INetURLObject::FSYS_DETECT );
512 
513     FASTBOOL bChanged =
514 #ifdef UNX
515 // Unix is case sensitive
516         ( sNewPathStr != sWritable );
517 #else
518         ( sNewPathStr.CompareIgnoreCaseToAscii( sWritable ) != COMPARE_EQUAL );
519 #endif
520 
521     if ( bChanged )
522     {
523         pPathBox->SetEntryText( Convert_Impl( sNewPathStr ), pEntry, 1 );
524         nPos = (sal_uInt16)pPathBox->GetModel()->GetAbsPos( pEntry );
525         pPathImpl = (PathUserData_Impl*)pPathBox->GetEntry(nPos)->GetUserData();
526         pPathImpl->eState = SFX_ITEM_SET;
527         pPathImpl->sWritablePath = sNewPathStr;
528         if ( SvtPathOptions::PATH_WORK == pPathImpl->nRealId )
529         {
530             // Remove view options entry so the new work path
531             // will be used for the next open dialog.
532             SvtViewOptions aDlgOpt( E_DIALOG, IODLG_CONFIGNAME );
533             aDlgOpt.Delete();
534 		    // Reset also last used dir in the sfx application instance
535             SfxApplication *pSfxApp = SFX_APP();
536 		    pSfxApp->ResetLastDir();
537 
538     		// Set configuration flag to notify file picker that it's necessary
539             // to take over the path provided.
540             Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
541             ::comphelper::ConfigurationHelper::writeDirectKey(xFactory,
542                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Common/")),
543                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Path/Info")),
544                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("WorkPathChanged")),
545                 ::com::sun::star::uno::makeAny(true),
546                 ::comphelper::ConfigurationHelper::E_STANDARD);
547         }
548     }
549 }
550 
551 // -----------------------------------------------------------------------
552 
IMPL_LINK(SvxPathTabPage,PathHdl_Impl,PushButton *,EMPTYARG)553 IMPL_LINK( SvxPathTabPage, PathHdl_Impl, PushButton *, EMPTYARG )
554 {
555 	SvLBoxEntry* pEntry = pPathBox->GetCurEntry();
556 	sal_uInt16 nPos = ( pEntry != NULL ) ? ( (PathUserData_Impl*)pEntry->GetUserData() )->nRealId : 0;
557     String sInternal, sUser, sWritable;
558 	if ( pEntry )
559 	{
560 		PathUserData_Impl* pPathImpl = (PathUserData_Impl*)pEntry->GetUserData();
561         sal_Bool bReadOnly = sal_False;
562         GetPathList( pPathImpl->nRealId, sInternal, sUser, sWritable, bReadOnly );
563         sUser = pPathImpl->sUserPath;
564         sWritable = pPathImpl->sWritablePath;
565 	}
566 
567     if(pEntry && !(!((OptHeaderTabListBox*)pPathBox)->GetCollapsedEntryBmp(pEntry)))
568         return 0;
569 
570 	if ( IsMultiPath_Impl( nPos ) )
571 	{
572 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
573         if ( pFact )
574 		{
575             AbstractSvxMultiPathDialog* pMultiDlg =
576                 pFact->CreateSvxMultiPathDialog( this );
577             DBG_ASSERT( pMultiDlg, "Dialogdiet fail!" );
578             pMultiDlg->EnableRadioButtonMode();
579 
580             String sPath( sUser );
581             if ( sPath.Len() > 0 )
582                 sPath += MULTIPATH_DELIMITER;
583             sPath += sWritable;
584             pMultiDlg->SetPath( sPath );
585 
586             String sPathName = pPathBox->GetEntryText( pEntry, 0 );
587             String sNewTitle( pImpl->m_sMultiPathDlg );
588             sNewTitle.SearchAndReplace( VAR_ONE, sPathName );
589             pMultiDlg->SetTitle( sNewTitle );
590 
591             if ( pMultiDlg->Execute() == RET_OK && pEntry )
592 			{
593                 sUser.Erase();
594                 sWritable.Erase();
595                 String sFullPath;
596                 String sNewPath = pMultiDlg->GetPath();
597                 char cDelim = MULTIPATH_DELIMITER;
598                 sal_uInt16 nCount = sNewPath.GetTokenCount( cDelim );
599                 if ( nCount > 0 )
600                 {
601                     sal_uInt16 i = 0;
602                     for ( ; i < nCount - 1; ++i )
603                     {
604                         if ( sUser.Len() > 0 )
605                             sUser += cDelim;
606                         sUser += sNewPath.GetToken( i, cDelim );
607                     }
608                     if ( sFullPath.Len() > 0 )
609                         sFullPath += cDelim;
610                     sFullPath += sUser;
611                     sWritable += sNewPath.GetToken( i, cDelim );
612                     if ( sFullPath.Len() > 0 )
613                         sFullPath += cDelim;
614                     sFullPath += sWritable;
615                 }
616 
617                 pPathBox->SetEntryText( Convert_Impl( sFullPath ), pEntry, 1 );
618                 // save modified flag
619                 PathUserData_Impl* pPathImpl = (PathUserData_Impl*)pEntry->GetUserData();
620 				pPathImpl->eState = SFX_ITEM_SET;
621                 pPathImpl->sUserPath = sUser;
622                 pPathImpl->sWritablePath = sWritable;
623             }
624             delete pMultiDlg;
625 		}
626 	}
627 	else if ( pEntry )
628 	{
629         try
630         {
631     		rtl::OUString aService( RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_SERVICE_NAME ) );
632     		Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
633             xFolderPicker = ::com::sun::star::uno::Reference< XFolderPicker >(
634                 xFactory->createInstance( aService ), UNO_QUERY );
635 
636             INetURLObject aURL( sWritable, INET_PROT_FILE );
637         	xFolderPicker->setDisplayDirectory( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
638 
639             Reference< XAsynchronousExecutableDialog > xAsyncDlg( xFolderPicker, UNO_QUERY );
640             if ( xAsyncDlg.is() )
641                 xAsyncDlg->startExecuteModal( xDialogListener.get() );
642             else
643             {
644                 short nRet = xFolderPicker->execute();
645                 if ( ExecutableDialogResults::OK != nRet )
646                     return 0;
647 
648                 String sFolder( xFolderPicker->getDirectory() );
649                 ChangeCurrentEntry( sFolder );
650             }
651 		}
652         catch( Exception& )
653         {
654             DBG_ERRORFILE( "SvxPathTabPage::PathHdl_Impl: exception from folder picker" );
655         }
656 	}
657 	return 0;
658 }
659 
660 // -----------------------------------------------------------------------
661 
IMPL_LINK(SvxPathTabPage,HeaderSelect_Impl,HeaderBar *,pBar)662 IMPL_LINK( SvxPathTabPage, HeaderSelect_Impl, HeaderBar*, pBar )
663 {
664 	if ( pBar && pBar->GetCurItemId() != ITEMID_TYPE )
665 		return 0;
666 
667 	HeaderBarItemBits nBits	= pHeaderBar->GetItemBits(ITEMID_TYPE);
668 	sal_Bool bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
669 	SvSortMode eMode = SortAscending;
670 
671 	if ( bUp )
672 	{
673 		nBits &= ~HIB_UPARROW;
674 		nBits |= HIB_DOWNARROW;
675 		eMode = SortDescending;
676 	}
677 	else
678 	{
679 		nBits &= ~HIB_DOWNARROW;
680 		nBits |= HIB_UPARROW;
681 	}
682 	pHeaderBar->SetItemBits( ITEMID_TYPE, nBits );
683 	SvTreeList* pModel = pPathBox->GetModel();
684 	pModel->SetSortMode( eMode );
685 	pModel->Resort();
686 	return 1;
687 }
688 
689 // -----------------------------------------------------------------------
690 
IMPL_LINK(SvxPathTabPage,HeaderEndDrag_Impl,HeaderBar *,pBar)691 IMPL_LINK( SvxPathTabPage, HeaderEndDrag_Impl, HeaderBar*, pBar )
692 {
693 	if ( pBar && !pBar->GetCurItemId() )
694 		return 0;
695 
696 	if ( !pHeaderBar->IsItemMode() )
697 	{
698 		Size aSz;
699 		sal_uInt16 nTabs = pHeaderBar->GetItemCount();
700 		long nTmpSz = 0;
701 		long nWidth = pHeaderBar->GetItemSize(ITEMID_TYPE);
702 		long nBarWidth = pHeaderBar->GetSizePixel().Width();
703 
704         if(nWidth < TAB_WIDTH_MIN)
705             pHeaderBar->SetItemSize( ITEMID_TYPE, TAB_WIDTH_MIN);
706         else if ( ( nBarWidth - nWidth ) < TAB_WIDTH_MIN )
707             pHeaderBar->SetItemSize( ITEMID_TYPE, nBarWidth - TAB_WIDTH_MIN );
708 
709 		for ( sal_uInt16 i = 1; i <= nTabs; ++i )
710 		{
711 			long _nWidth = pHeaderBar->GetItemSize(i);
712 			aSz.Width() =  _nWidth + nTmpSz;
713 			nTmpSz += _nWidth;
714 			pPathBox->SetTab( i, PixelToLogic( aSz, MapMode(MAP_APPFONT) ).Width(), MAP_APPFONT );
715 		}
716 	}
717 	return 1;
718 }
719 
720 // -----------------------------------------------------------------------
721 
IMPL_LINK(SvxPathTabPage,DialogClosedHdl,DialogClosedEvent *,pEvt)722 IMPL_LINK( SvxPathTabPage, DialogClosedHdl, DialogClosedEvent*, pEvt )
723 {
724     if ( RET_OK == pEvt->DialogResult )
725     {
726         DBG_ASSERT( xFolderPicker.is() == sal_True, "SvxPathTabPage::DialogClosedHdl(): no folder picker" );
727 
728         String sURL = String( xFolderPicker->getDirectory() );
729         ChangeCurrentEntry( sURL );
730     }
731     return 0L;
732 }
733 
734 // -----------------------------------------------------------------------
735 
GetPathList(sal_uInt16 _nPathHandle,String & _rInternalPath,String & _rUserPath,String & _rWritablePath,sal_Bool & _rReadOnly)736 void SvxPathTabPage::GetPathList(
737     sal_uInt16 _nPathHandle, String& _rInternalPath,
738     String& _rUserPath, String& _rWritablePath, sal_Bool& _rReadOnly )
739 {
740     String sCfgName = getCfgName_Impl( _nPathHandle );
741 
742     // load PathSettings service if necessary
743     if ( !pImpl->m_xPathSettings.is() )
744     {
745         Reference< XMultiServiceFactory > xSMgr = comphelper::getProcessServiceFactory();
746         pImpl->m_xPathSettings = Reference< XPropertySet >( xSMgr->createInstance(
747             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
748                 "com.sun.star.util.PathSettings") ) ), UNO_QUERY );
749     }
750 
751     try
752     {
753         if ( pImpl->m_xPathSettings.is() )
754         {
755             // load internal paths
756             String sProp( sCfgName );
757             sProp = sCfgName;
758             sProp += POSTFIX_INTERNAL;
759             Any aAny = pImpl->m_xPathSettings->getPropertyValue( sProp );
760             Sequence< ::rtl::OUString > aPathSeq;
761             if ( aAny >>= aPathSeq )
762             {
763                 long i, nCount = aPathSeq.getLength();
764                 const ::rtl::OUString* pPaths = aPathSeq.getConstArray();
765 
766                 for ( i = 0; i < nCount; ++i )
767                 {
768                     if ( _rInternalPath.Len() > 0 )
769                         _rInternalPath += ';';
770                     _rInternalPath += String( pPaths[i] );
771                 }
772             }
773             // load user paths
774             sProp = sCfgName;
775             sProp += POSTFIX_USER;
776             aAny = pImpl->m_xPathSettings->getPropertyValue( sProp );
777             if ( aAny >>= aPathSeq )
778             {
779                 long i, nCount = aPathSeq.getLength();
780                 const ::rtl::OUString* pPaths = aPathSeq.getConstArray();
781 
782                 for ( i = 0; i < nCount; ++i )
783                 {
784                     if ( _rUserPath.Len() > 0 )
785                         _rUserPath += ';';
786                     _rUserPath += String( pPaths[i] );
787                 }
788             }
789             // then the writable path
790             sProp = sCfgName;
791             sProp += POSTFIX_WRITABLE;
792             aAny = pImpl->m_xPathSettings->getPropertyValue( sProp );
793             ::rtl::OUString sWritablePath;
794             if ( aAny >>= sWritablePath )
795                 _rWritablePath = String( sWritablePath );
796 
797             // and the readonly flag
798             sProp = sCfgName;
799             Reference< XPropertySetInfo > xInfo = pImpl->m_xPathSettings->getPropertySetInfo();
800             Property aProp = xInfo->getPropertyByName( sProp );
801             _rReadOnly = ( ( aProp.Attributes & PropertyAttribute::READONLY ) == PropertyAttribute::READONLY );
802         }
803     }
804     catch( const Exception& )
805     {
806         OSL_ENSURE( sal_False, "SvxPathTabPage::GetPathList(): caught an exception!" );
807     }
808 }
809 
810 // -----------------------------------------------------------------------
811 
SetPathList(sal_uInt16 _nPathHandle,const String & _rUserPath,const String & _rWritablePath)812 void SvxPathTabPage::SetPathList(
813     sal_uInt16 _nPathHandle, const String& _rUserPath, const String& _rWritablePath )
814 {
815     String sCfgName = getCfgName_Impl( _nPathHandle );
816 
817     // load PathSettings service if necessary
818     if ( !pImpl->m_xPathSettings.is() )
819     {
820         Reference< XMultiServiceFactory > xSMgr = comphelper::getProcessServiceFactory();
821         pImpl->m_xPathSettings = Reference< XPropertySet >( xSMgr->createInstance(
822             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
823                 "com.sun.star.util.PathSettings") ) ), UNO_QUERY );
824     }
825 
826     try
827     {
828         if ( pImpl->m_xPathSettings.is() )
829         {
830             // save user paths
831             char cDelim = MULTIPATH_DELIMITER;
832             sal_uInt16 nCount = _rUserPath.GetTokenCount( cDelim );
833             Sequence< ::rtl::OUString > aPathSeq( nCount );
834             ::rtl::OUString* pArray = aPathSeq.getArray();
835             for ( sal_uInt16 i = 0; i < nCount; ++i )
836                 pArray[i] = ::rtl::OUString( _rUserPath.GetToken( i, cDelim ) );
837             String sProp( sCfgName );
838             sProp += POSTFIX_USER;
839             Any aValue = makeAny( aPathSeq );
840             pImpl->m_xPathSettings->setPropertyValue( sProp, aValue );
841 
842             // then the writable path
843             aValue = makeAny( ::rtl::OUString( _rWritablePath ) );
844             sProp = sCfgName;
845             sProp += POSTFIX_WRITABLE;
846             pImpl->m_xPathSettings->setPropertyValue( sProp, aValue );
847         }
848     }
849     catch( const Exception& )
850     {
851         OSL_ENSURE( sal_False, "SvxPathTabPage::SetPathList(): caught an exception!" );
852     }
853 }
854 
855