1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sfxpicklist.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include <com/sun/star/document/XDocumentProperties.hpp>
35 #include <svtools/historyoptions.hxx>
36 #include <svtools/useroptions.hxx>
37 #include <tools/urlobj.hxx>
38 #include <framework/menuconfiguration.hxx>
39 #include <svtools/inethist.hxx>
40 #include <svtools/stritem.hxx>
41 #include <svtools/eitem.hxx>
42 #include <osl/file.hxx>
43 #include <unotools/localfilehelper.hxx>
44 #include <cppuhelper/implbase1.hxx>
46 #include <shell/systemshell.hxx>
48 // ----------------------------------------------------------------------------
50 #include <sfx2/app.hxx>
51 #include "sfxpicklist.hxx"
52 #include <sfx2/sfxuno.hxx>
53 #include "sfxtypes.hxx"
54 #include <sfx2/request.hxx>
55 #include <sfx2/sfxsids.hrc>
56 #include <sfx2/sfx.hrc>
57 #include <sfx2/event.hxx>
58 #include <sfx2/objsh.hxx>
59 #include <sfx2/bindings.hxx>
60 #include "referers.hxx"
61 #include <sfx2/docfile.hxx>
62 #include "objshimp.hxx"
63 #include <sfx2/docfilt.hxx>
67 // ----------------------------------------------------------------------------
69 using namespace ::com::sun::star::uno
;
70 using namespace ::com::sun::star::beans
;
71 using namespace ::com::sun::star::util
;
73 // ----------------------------------------------------------------------------
75 osl::Mutex
* SfxPickList::pMutex
= 0;
76 SfxPickList
* SfxPickList::pUniqueInstance
= 0;
78 // ----------------------------------------------------------------------------
80 class StringLength
: public ::cppu::WeakImplHelper1
< XStringWidth
>
84 virtual ~StringLength() {}
87 sal_Int32 SAL_CALL
queryStringWidth( const ::rtl::OUString
& aString
)
88 throw (::com::sun::star::uno::RuntimeException
)
90 return aString
.getLength();
94 // ----------------------------------------------------------------------------
96 osl::Mutex
* SfxPickList::GetOrCreateMutex()
100 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
102 pMutex
= new osl::Mutex
;
108 void SfxPickList::CreatePicklistMenuTitle( Menu
* pMenu
, USHORT nItemId
, const String
& aURLString
, sal_uInt32 nNo
)
115 aPickEntry
+= String::CreateFromInt32( nNo
+ 1 );
118 aPickEntry
+= DEFINE_CONST_UNICODE("1~0");
120 aPickEntry
+= String::CreateFromInt32( nNo
+ 1 );
121 aPickEntry
+= DEFINE_CONST_UNICODE(": ");
123 INetURLObject
aURL( aURLString
);
124 rtl::OUString aTipHelpText
;
125 rtl::OUString
aAccessibleName( aPickEntry
);
127 if ( aURL
.GetProtocol() == INET_PROT_FILE
)
129 // Do handle file URL differently => convert it to a system
130 // path and abbreviate it with a special function:
131 String
aFileSystemPath( aURL
.getFSysPath( INetURLObject::FSYS_DETECT
) );
133 // ::utl::LocalFileHelper::ConvertURLToPhysicalName( aURLString, aPhysicalName );
135 ::rtl::OUString
aSystemPath( aFileSystemPath
);
136 ::rtl::OUString aCompactedSystemPath
;
138 aTipHelpText
= aSystemPath
;
139 aAccessibleName
+= aSystemPath
;
140 oslFileError nError
= osl_abbreviateSystemPath( aSystemPath
.pData
, &aCompactedSystemPath
.pData
, 46, NULL
);
142 aPickEntry
+= String( aCompactedSystemPath
);
144 aPickEntry
+= aFileSystemPath
;
146 if ( aPickEntry
.Len() > 50 )
148 aPickEntry
.Erase( 47 );
149 aPickEntry
+= DEFINE_CONST_UNICODE("...");
154 // Use INetURLObject to abbreviate all other URLs
156 aShortURL
= aURL
.getAbbreviated( m_xStringLength
, 46, INetURLObject::DECODE_UNAMBIGUOUS
);
157 aPickEntry
+= aShortURL
;
158 aTipHelpText
= aURLString
;
159 aAccessibleName
+= aURLString
;
162 // Set menu item text, tip help and accessible name
163 pMenu
->SetItemText( nItemId
, aPickEntry
);
164 pMenu
->SetTipHelpText( nItemId
, aTipHelpText
);
165 pMenu
->SetAccessibleName( nItemId
, aAccessibleName
);
168 void SfxPickList::RemovePickListEntries()
170 ::osl::MutexGuard
aGuard( GetOrCreateMutex() );
171 for ( sal_uInt32 i
= 0; i
< m_aPicklistVector
.size(); i
++ )
172 delete m_aPicklistVector
[i
];
173 m_aPicklistVector
.clear();
176 SfxPickList::PickListEntry
* SfxPickList::GetPickListEntry( sal_uInt32 nIndex
)
178 OSL_ASSERT( m_aPicklistVector
.size() > nIndex
);
180 if ( nIndex
< m_aPicklistVector
.size() )
181 return m_aPicklistVector
[ nIndex
];
186 SfxPickList
* SfxPickList::GetOrCreate( const sal_uInt32 nMenuSize
)
188 if ( !pUniqueInstance
)
190 ::osl::MutexGuard
aGuard( GetOrCreateMutex() );
191 if ( !pUniqueInstance
)
192 pUniqueInstance
= new SfxPickList( nMenuSize
);
195 return pUniqueInstance
;
198 SfxPickList
* SfxPickList::Get()
200 ::osl::MutexGuard
aGuard( GetOrCreateMutex() );
201 return pUniqueInstance
;
204 void SfxPickList::Delete()
206 ::osl::MutexGuard
aGuard( GetOrCreateMutex() );
207 DELETEZ( pUniqueInstance
);
210 SfxPickList::SfxPickList( sal_uInt32 nAllowedMenuSize
) :
211 m_nAllowedMenuSize( nAllowedMenuSize
)
213 m_xStringLength
= new StringLength
;
214 m_nAllowedMenuSize
= ::std::min( m_nAllowedMenuSize
, (sal_uInt32
)PICKLIST_MAXSIZE
);
215 StartListening( *SFX_APP() );
218 SfxPickList::~SfxPickList()
220 RemovePickListEntries();
223 void SfxPickList::CreatePickListEntries()
225 RemovePickListEntries();
227 // Einlesen der Pickliste
228 Sequence
< Sequence
< PropertyValue
> > seqPicklist
= SvtHistoryOptions().GetList( ePICKLIST
);
230 sal_uInt32 nCount
= seqPicklist
.getLength();
231 sal_uInt32 nEntries
= ::std::min( m_nAllowedMenuSize
, nCount
);
233 for( sal_uInt32 nItem
=0; nItem
< nEntries
; ++nItem
)
235 Sequence
< PropertyValue
> seqPropertySet
= seqPicklist
[ nItem
];
238 ::rtl::OUString sURL
;
239 ::rtl::OUString sFilter
;
240 ::rtl::OUString sTitle
;
241 ::rtl::OUString sPassword
;
243 sal_uInt32 nPropertyCount
= seqPropertySet
.getLength();
244 for( sal_uInt32 nProperty
=0; nProperty
<nPropertyCount
; ++nProperty
)
246 if( seqPropertySet
[nProperty
].Name
== HISTORY_PROPERTYNAME_URL
)
248 seqPropertySet
[nProperty
].Value
>>= sURL
;
250 else if( seqPropertySet
[nProperty
].Name
== HISTORY_PROPERTYNAME_FILTER
)
252 seqPropertySet
[nProperty
].Value
>>= sFilter
;
254 else if( seqPropertySet
[nProperty
].Name
== HISTORY_PROPERTYNAME_TITLE
)
256 seqPropertySet
[nProperty
].Value
>>= sTitle
;
258 else if( seqPropertySet
[nProperty
].Name
== HISTORY_PROPERTYNAME_PASSWORD
)
260 seqPropertySet
[nProperty
].Value
>>= sPassword
;
264 aURL
.SetSmartURL( sURL
);
265 aURL
.SetPass( SfxStringDecode( sPassword
) );
267 PickListEntry
*pPick
= new PickListEntry( aURL
.GetMainURL( INetURLObject::NO_DECODE
), sFilter
, sTitle
);
268 m_aPicklistVector
.push_back( pPick
);
272 void SfxPickList::CreateMenuEntries( Menu
* pMenu
)
274 static sal_Bool bPickListMenuInitializing
= sal_False
;
276 ::osl::MutexGuard
aGuard( GetOrCreateMutex() );
278 if ( bPickListMenuInitializing
) // method is not reentrant!
281 bPickListMenuInitializing
= sal_True
;
282 CreatePickListEntries();
284 for ( sal_uInt16 nId
= START_ITEMID_PICKLIST
; nId
<= END_ITEMID_PICKLIST
; ++nId
)
285 pMenu
->RemoveItem( pMenu
->GetItemPos( nId
) );
287 if ( pMenu
->GetItemType( pMenu
->GetItemCount()-1 ) == MENUITEM_SEPARATOR
)
288 pMenu
->RemoveItem( pMenu
->GetItemCount()-1 );
290 if ( m_aPicklistVector
.size() > 0 &&
291 pMenu
->GetItemType( pMenu
->GetItemCount()-1 )
292 != MENUITEM_SEPARATOR
&& m_nAllowedMenuSize
)
293 pMenu
->InsertSeparator();
295 rtl::OUString aEmptyString
;
296 for ( sal_uInt32 i
= 0; i
< m_aPicklistVector
.size(); i
++ )
298 PickListEntry
* pEntry
= GetPickListEntry( i
);
300 pMenu
->InsertItem( (USHORT
)(START_ITEMID_PICKLIST
+ i
), aEmptyString
);
301 CreatePicklistMenuTitle( pMenu
, (USHORT
)(START_ITEMID_PICKLIST
+ i
), pEntry
->aName
, i
);
304 bPickListMenuInitializing
= sal_False
;
307 void SfxPickList::ExecuteEntry( sal_uInt32 nIndex
)
309 ::osl::ClearableMutexGuard
aGuard( GetOrCreateMutex() );
311 PickListEntry
*pPick
= SfxPickList::Get()->GetPickListEntry( nIndex
);
315 SfxRequest
aReq( SID_OPENDOC
, SFX_CALLMODE_ASYNCHRON
, SFX_APP()->GetPool() );
316 aReq
.AppendItem( SfxStringItem( SID_FILE_NAME
, pPick
->aName
));
317 aReq
.AppendItem( SfxStringItem( SID_REFERER
, DEFINE_CONST_UNICODE( SFX_REFERER_USER
) ) );
318 aReq
.AppendItem( SfxStringItem( SID_TARGETNAME
, DEFINE_CONST_UNICODE("_default") ) );
319 String
aFilter( pPick
->aFilter
);
322 USHORT nPos
=aFilter
.Search('|');
323 if( nPos
!= STRING_NOTFOUND
)
325 String
aOptions(aFilter
.Copy( nPos
).GetBuffer()+1);
326 aFilter
.Erase( nPos
);
327 aReq
.AppendItem( SfxStringItem(SID_FILE_FILTEROPTIONS
, aOptions
));
330 aReq
.AppendItem(SfxStringItem( SID_FILTER_NAME
, aFilter
));
331 aReq
.AppendItem( SfxBoolItem( SID_TEMPLATE
, sal_False
) );
332 SFX_APP()->ExecuteSlot( aReq
);
336 void SfxPickList::ExecuteMenuEntry( USHORT nId
)
338 ExecuteEntry( (sal_uInt32
)( nId
- START_ITEMID_PICKLIST
) );
341 String
SfxPickList::GetMenuEntryTitle( sal_uInt32 nIndex
)
343 PickListEntry
*pPick
= SfxPickList::Get()->GetPickListEntry( nIndex
);
346 return pPick
->aTitle
;
351 void SfxPickList::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
353 if ( rHint
.IsA( TYPE( SfxStringHint
)))
355 SfxStringHint
* pStringHint
= (SfxStringHint
*) &rHint
;
357 if ( pStringHint
->GetId() == SID_OPENURL
)
358 INetURLHistory::GetOrCreate()->PutUrl( INetURLObject( pStringHint
->GetObject() ));
361 if ( rHint
.IsA( TYPE( SfxEventHint
)))
363 SfxEventHint
* pEventHint
= PTR_CAST(SfxEventHint
,&rHint
);
364 // nur ObjectShell-bezogene Events mit Medium interessieren
365 SfxObjectShell
* pDocSh
= pEventHint
->GetObjShell();
369 switch ( pEventHint
->GetEventId() )
371 case SFX_EVENT_CREATEDOC
:
373 sal_Bool bAllowModif
= pDocSh
->IsEnableSetModified();
375 pDocSh
->EnableSetModified( sal_False
);
377 using namespace ::com::sun::star
;
378 uno::Reference
<document::XDocumentProperties
> xDocProps(
379 pDocSh
->getDocProperties());
380 if (xDocProps
.is()) {
381 xDocProps
->setAuthor( SvtUserOptions().GetFullName() );
383 xDocProps
->setCreationDate( util::DateTime(
384 now
.Get100Sec(), now
.GetSec(), now
.GetMin(),
385 now
.GetHour(), now
.GetDay(), now
.GetMonth(),
390 pDocSh
->EnableSetModified( bAllowModif
);
394 case SFX_EVENT_OPENDOC
:
396 SfxMedium
*pMed
= pDocSh
->GetMedium();
400 // unbenannt-Docs und embedded-Docs nicht in History
401 if ( !pDocSh
->HasName() ||
402 SFX_CREATE_MODE_STANDARD
!= pDocSh
->GetCreateMode() )
405 // Hilfe nicht in History
406 INetURLObject
aURL( pDocSh
->IsDocShared() ? pDocSh
->GetSharedFileURL() : ::rtl::OUString( pMed
->GetOrigURL() ) );
407 if ( aURL
.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP
)
410 ::rtl::OUString aTitle
= pDocSh
->GetTitle(SFX_TITLE_PICKLIST
);
411 ::rtl::OUString aFilter
;
412 const SfxFilter
* pFilter
= pMed
->GetOrigFilter();
414 aFilter
= pFilter
->GetFilterName();
416 // add to svtool history options
417 SvtHistoryOptions().AppendItem( eHISTORY
,
418 aURL
.GetURLNoPass( INetURLObject::NO_DECODE
),
421 SfxStringEncode( aURL
.GetPass() ) );
425 case SFX_EVENT_CLOSEDOC
:
427 SfxMedium
*pMed
= pDocSh
->GetMedium();
431 // unbenannt-Docs und embedded-Docs nicht in Pickliste
432 if ( !pDocSh
->HasName() ||
433 SFX_CREATE_MODE_STANDARD
!= pDocSh
->GetCreateMode() )
436 // Hilfe nicht in History
437 INetURLObject
aURL( pDocSh
->IsDocShared() ? pDocSh
->GetSharedFileURL() : ::rtl::OUString( pMed
->GetOrigURL() ) );
438 if ( aURL
.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP
)
441 // only add r/w document into picklist
442 if ( pDocSh
->IsReadOnly() || !pMed
->IsUpdatePickList() )
445 // add no document that forbids this (for example Message-Body)
446 SFX_ITEMSET_ARG( pMed
->GetItemSet(), pPicklistItem
, SfxBoolItem
, SID_PICKLIST
, sal_False
);
448 (pPicklistItem
&& !pPicklistItem
->GetValue()) ||
449 (!(pDocSh
->Get_Impl()->bWaitingForPicklist
) )
453 // ignore hidden documents
454 if ( !SfxViewFrame::GetFirst( pDocSh
, 0, TRUE
) )
457 ::rtl::OUString aTitle
= pDocSh
->GetTitle(SFX_TITLE_PICKLIST
);
458 ::rtl::OUString aFilter
;
459 const SfxFilter
* pFilter
= pMed
->GetOrigFilter();
461 aFilter
= pFilter
->GetFilterName();
463 // add to svtool history options
464 SvtHistoryOptions().AppendItem( ePICKLIST
,
465 aURL
.GetURLNoPass( INetURLObject::NO_DECODE
),
468 SfxStringEncode( aURL
.GetPass() ) );
470 pDocSh
->Get_Impl()->bWaitingForPicklist
= sal_False
;
472 if ( aURL
.GetProtocol() == INET_PROT_FILE
)
473 SystemShell::AddToRecentDocumentList( aURL
.GetURLNoPass( INetURLObject::NO_DECODE
), (pFilter
) ? pFilter
->GetMimeType() : String() );